Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
7 changes: 5 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ typings/

# Nuxt.js build / generate output
.nuxt
dist
# dist

# Gatsby files
.cache/
Expand All @@ -107,4 +107,7 @@ dist
.idea

# TypeScript build files
build/
build/


.DS_Store
8 changes: 1 addition & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@

## What is py-slang?

`py-slang` is a language frontend for the
[js-slang](https://github.com/source-academy/js-slang) repository. It parses
a restricted subset of Python (enough to complete SICP), and outputs an
`estree`-compatible AST. [The grammar](./src/Grammar.gram) is a reduced
version of [Python 3.7's](https://docs.python.org/3.7/reference/grammar.html).
This project does not aim to be a full Python to JS transpiler, but aims
to transpile just a small enough subset of Python.
`py-slang` is a Python implementation developed specifically for the Source Academy online learning environment. Unlike previous versions where Python was treated as a subset within [js-slang](https://github.com/source-academy/js-slang), py-slang now stands as an independent language implementation. It features its own parser, csemachine, and runtime, designed to process a tailored subset of Python for educational purposes.

## Usage
For local testing:
Expand Down
234 changes: 234 additions & 0 deletions dist/ast-types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
import { Token } from "./tokenizer";
import { PyComplexNumber } from "./types";
export declare namespace ExprNS {
interface Visitor<T> {
visitBigIntLiteralExpr(expr: BigIntLiteral): T;
visitBinaryExpr(expr: Binary): T;
visitCompareExpr(expr: Compare): T;
visitBoolOpExpr(expr: BoolOp): T;
visitGroupingExpr(expr: Grouping): T;
visitLiteralExpr(expr: Literal): T;
visitUnaryExpr(expr: Unary): T;
visitTernaryExpr(expr: Ternary): T;
visitLambdaExpr(expr: Lambda): T;
visitMultiLambdaExpr(expr: MultiLambda): T;
visitVariableExpr(expr: Variable): T;
visitCallExpr(expr: Call): T;
visitComplexExpr(expr: Complex): T;
visitNoneExpr(expr: None): T;
}
abstract class Expr {
startToken: Token;
endToken: Token;
protected constructor(startToken: Token, endToken: Token);
abstract accept(visitor: Visitor<any>): any;
}
class None extends Expr {
constructor(startToken: Token, endToken: Token, value?: string);
accept(visitor: Visitor<any>): any;
}
class BigIntLiteral extends Expr {
value: string;
constructor(startToken: Token, endToken: Token, value: string);
accept(visitor: Visitor<any>): any;
}
class Complex extends Expr {
value: PyComplexNumber;
constructor(startToken: Token, endToken: Token, value: string);
accept<T>(visitor: Visitor<T>): T;
}
class Binary extends Expr {
left: Expr;
operator: Token;
right: Expr;
constructor(startToken: Token, endToken: Token, left: Expr, operator: Token, right: Expr);
accept(visitor: Visitor<any>): any;
}
class Compare extends Expr {
left: Expr;
operator: Token;
right: Expr;
constructor(startToken: Token, endToken: Token, left: Expr, operator: Token, right: Expr);
accept(visitor: Visitor<any>): any;
}
class BoolOp extends Expr {
left: Expr;
operator: Token;
right: Expr;
constructor(startToken: Token, endToken: Token, left: Expr, operator: Token, right: Expr);
accept(visitor: Visitor<any>): any;
}
class Grouping extends Expr {
expression: Expr;
constructor(startToken: Token, endToken: Token, expression: Expr);
accept(visitor: Visitor<any>): any;
}
class Literal extends Expr {
value: true | false | number | string;
constructor(startToken: Token, endToken: Token, value: true | false | number | string);
accept(visitor: Visitor<any>): any;
}
class Unary extends Expr {
operator: Token;
right: Expr;
constructor(startToken: Token, endToken: Token, operator: Token, right: Expr);
accept(visitor: Visitor<any>): any;
}
class Ternary extends Expr {
predicate: Expr;
consequent: Expr;
alternative: Expr;
constructor(startToken: Token, endToken: Token, predicate: Expr, consequent: Expr, alternative: Expr);
accept(visitor: Visitor<any>): any;
}
class Lambda extends Expr {
parameters: Token[];
body: Expr;
constructor(startToken: Token, endToken: Token, parameters: Token[], body: Expr);
accept(visitor: Visitor<any>): any;
}
class MultiLambda extends Expr {
parameters: Token[];
body: StmtNS.Stmt[];
varDecls: Token[];
constructor(startToken: Token, endToken: Token, parameters: Token[], body: StmtNS.Stmt[], varDecls: Token[]);
accept(visitor: Visitor<any>): any;
}
class Variable extends Expr {
name: Token;
constructor(startToken: Token, endToken: Token, name: Token);
accept(visitor: Visitor<any>): any;
}
class Call extends Expr {
callee: Expr;
args: Expr[];
constructor(startToken: Token, endToken: Token, callee: Expr, args: Expr[]);
accept(visitor: Visitor<any>): any;
}
}
export declare namespace StmtNS {
interface Visitor<T> {
visitIndentCreation(stmt: Indent): T;
visitDedentCreation(stmt: Dedent): T;
visitPassStmt(stmt: Pass): T;
visitAssignStmt(stmt: Assign): T;
visitAnnAssignStmt(stmt: AnnAssign): T;
visitBreakStmt(stmt: Break): T;
visitContinueStmt(stmt: Continue): T;
visitReturnStmt(stmt: Return): T;
visitFromImportStmt(stmt: FromImport): T;
visitGlobalStmt(stmt: Global): T;
visitNonLocalStmt(stmt: NonLocal): T;
visitAssertStmt(stmt: Assert): T;
visitIfStmt(stmt: If): T;
visitWhileStmt(stmt: While): T;
visitForStmt(stmt: For): T;
visitFunctionDefStmt(stmt: FunctionDef): T;
visitSimpleExprStmt(stmt: SimpleExpr): T;
visitFileInputStmt(stmt: FileInput): T;
}
abstract class Stmt {
startToken: Token;
endToken: Token;
protected constructor(startToken: Token, endToken: Token);
abstract accept(visitor: Visitor<any>): any;
}
class Indent extends Stmt {
constructor(startToken: Token, endToken: Token);
accept(visitor: Visitor<any>): any;
}
class Dedent extends Stmt {
constructor(startToken: Token, endToken: Token);
accept(visitor: Visitor<any>): any;
}
class Pass extends Stmt {
constructor(startToken: Token, endToken: Token);
accept(visitor: Visitor<any>): any;
}
class Assign extends Stmt {
name: Token;
value: ExprNS.Expr;
constructor(startToken: Token, endToken: Token, name: Token, value: ExprNS.Expr);
accept(visitor: Visitor<any>): any;
}
class AnnAssign extends Stmt {
name: Token;
value: ExprNS.Expr;
ann: ExprNS.Expr;
constructor(startToken: Token, endToken: Token, name: Token, value: ExprNS.Expr, ann: ExprNS.Expr);
accept(visitor: Visitor<any>): any;
}
class Break extends Stmt {
constructor(startToken: Token, endToken: Token);
accept(visitor: Visitor<any>): any;
}
class Continue extends Stmt {
constructor(startToken: Token, endToken: Token);
accept(visitor: Visitor<any>): any;
}
class Return extends Stmt {
value: ExprNS.Expr | null;
constructor(startToken: Token, endToken: Token, value: ExprNS.Expr | null);
accept(visitor: Visitor<any>): any;
}
class FromImport extends Stmt {
module: Token;
names: Token[];
constructor(startToken: Token, endToken: Token, module: Token, names: Token[]);
accept(visitor: Visitor<any>): any;
}
class Global extends Stmt {
name: Token;
constructor(startToken: Token, endToken: Token, name: Token);
accept(visitor: Visitor<any>): any;
}
class NonLocal extends Stmt {
name: Token;
constructor(startToken: Token, endToken: Token, name: Token);
accept(visitor: Visitor<any>): any;
}
class Assert extends Stmt {
value: ExprNS.Expr;
constructor(startToken: Token, endToken: Token, value: ExprNS.Expr);
accept(visitor: Visitor<any>): any;
}
class If extends Stmt {
condition: ExprNS.Expr;
body: Stmt[];
elseBlock: Stmt[] | null;
constructor(startToken: Token, endToken: Token, condition: ExprNS.Expr, body: Stmt[], elseBlock: Stmt[] | null);
accept(visitor: Visitor<any>): any;
}
class While extends Stmt {
condition: ExprNS.Expr;
body: Stmt[];
constructor(startToken: Token, endToken: Token, condition: ExprNS.Expr, body: Stmt[]);
accept(visitor: Visitor<any>): any;
}
class For extends Stmt {
target: Token;
iter: ExprNS.Expr;
body: Stmt[];
constructor(startToken: Token, endToken: Token, target: Token, iter: ExprNS.Expr, body: Stmt[]);
accept(visitor: Visitor<any>): any;
}
class FunctionDef extends Stmt {
name: Token;
parameters: Token[];
body: Stmt[];
varDecls: Token[];
constructor(startToken: Token, endToken: Token, name: Token, parameters: Token[], body: Stmt[], varDecls: Token[]);
accept(visitor: Visitor<any>): any;
}
class SimpleExpr extends Stmt {
expression: ExprNS.Expr;
constructor(startToken: Token, endToken: Token, expression: ExprNS.Expr);
accept(visitor: Visitor<any>): any;
}
class FileInput extends Stmt {
statements: Stmt[];
varDecls: Token[];
constructor(startToken: Token, endToken: Token, statements: Stmt[], varDecls: Token[]);
accept(visitor: Visitor<any>): any;
}
}
4 changes: 4 additions & 0 deletions dist/common/Constant.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export declare const enum Constant {
PROTOCOL_VERSION = 0,
PROTOCOL_MIN_VERSION = 0
}
8 changes: 8 additions & 0 deletions dist/common/ds/MessageQueue.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export declare class MessageQueue<T> {
private readonly __inputQueue;
private readonly __promiseQueue;
push(item: T): void;
pop(): Promise<T>;
tryPop(): T | undefined;
constructor();
}
30 changes: 30 additions & 0 deletions dist/common/ds/Queue.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* A stack-based queue implementation.
* `push` and `pop` run in amortized constant time.
*/
export declare class Queue<T> {
/** The output stack. */
private __s1;
/** The input stack. */
private __s2;
/**
* Adds an item to the queue.
* @param item The item to be added to the queue.
*/
push(item: T): void;
/**
* Removes an item from the queue.
* @returns The item removed from the queue.
* @throws If the queue is empty.
*/
pop(): T;
/**
* The length of the queue.
*/
get length(): number;
/**
* Makes a copy of the queue.
* @returns A copy of the queue.
*/
clone(): Queue<T>;
}
2 changes: 2 additions & 0 deletions dist/common/ds/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { MessageQueue } from "./MessageQueue";
export { Queue } from "./Queue";
9 changes: 9 additions & 0 deletions dist/common/errors/ConductorError.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ErrorType } from "./ErrorType";
/**
* Generic Conductor Error.
*/
export declare class ConductorError extends Error {
name: string;
readonly errorType: ErrorType | string;
constructor(message: string);
}
10 changes: 10 additions & 0 deletions dist/common/errors/ConductorInternalError.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ConductorError } from "./ConductorError";
import { ErrorType } from "./ErrorType";
/**
* Conductor internal error, probably caused by developer oversight.
*/
export declare class ConductorInternalError extends ConductorError {
name: string;
readonly errorType: ErrorType | string;
constructor(message: string);
}
8 changes: 8 additions & 0 deletions dist/common/errors/ErrorType.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export declare const enum ErrorType {
UNKNOWN = "__unknown",
INTERNAL = "__internal",
EVALUATOR = "__evaluator",
EVALUATOR_SYNTAX = "__evaluator_syntax",
EVALUATOR_TYPE = "__evaluator_type",
EVALUATOR_RUNTIME = "__evaluator_runtime"
}
14 changes: 14 additions & 0 deletions dist/common/errors/EvaluatorError.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ConductorError } from "./ConductorError";
import { ErrorType } from "./ErrorType";
/**
* Generic evaluation error, caused by a problem in user code.
*/
export declare class EvaluatorError extends ConductorError {
name: string;
readonly errorType: ErrorType | string;
readonly rawMessage: string;
readonly line?: number;
readonly column?: number;
readonly fileName?: string;
constructor(message: string, line?: number, column?: number, fileName?: string);
}
9 changes: 9 additions & 0 deletions dist/common/errors/EvaluatorRuntimeError.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ErrorType } from "./ErrorType";
import { EvaluatorError } from "./EvaluatorError";
/**
* Evaluator runtime error - some problem occurred while running the user code.
*/
export declare class EvaluatorRuntimeError extends EvaluatorError {
name: string;
readonly errorType: ErrorType | string;
}
9 changes: 9 additions & 0 deletions dist/common/errors/EvaluatorSyntaxError.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ErrorType } from "./ErrorType";
import { EvaluatorError } from "./EvaluatorError";
/**
* Evaluator syntax error - the user code does not follow the evaluator's prescribed syntax.
*/
export declare class EvaluatorSyntaxError extends EvaluatorError {
name: string;
readonly errorType: ErrorType | string;
}
13 changes: 13 additions & 0 deletions dist/common/errors/EvaluatorTypeError.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ErrorType } from "./ErrorType";
import { EvaluatorError } from "./EvaluatorError";
/**
* Evaluator type error - the user code is not well typed or provides values of incorrect type to external functions.
*/
export declare class EvaluatorTypeError extends EvaluatorError {
name: string;
readonly errorType: ErrorType | string;
readonly rawMessage: string;
readonly expected: string;
readonly actual: string;
constructor(message: string, expected: string, actual: string, line?: number, column?: number, fileName?: string);
}
Loading
Loading