updated grammar; better LinkedList example
This commit is contained in:
parent
3317626540
commit
63ab8998d4
169
examples/LinkedList.plsm
Normal file
169
examples/LinkedList.plsm
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
module test;
|
||||||
|
|
||||||
|
import stdlib/io;
|
||||||
|
import stdlib/heap;
|
||||||
|
import stdlib/err;
|
||||||
|
|
||||||
|
trait Collection<T> {
|
||||||
|
add(item: &T) -> void;
|
||||||
|
remove(item: &T) -> void;
|
||||||
|
contains(item: &T) -> bool;
|
||||||
|
|
||||||
|
size() -> u64;
|
||||||
|
|
||||||
|
isEmpty() -> bool = self.size() > 0;
|
||||||
|
isNotEmpty() -> bool = self.size() <= 0;
|
||||||
|
|
||||||
|
each(fn: (item: &T, break: () -> void) -> void) -> void;
|
||||||
|
|
||||||
|
any(fn: (&T) -> bool) -> bool {
|
||||||
|
let mut res = false;
|
||||||
|
|
||||||
|
self.each((item, break) -> {
|
||||||
|
if fn(item) {
|
||||||
|
res = true;
|
||||||
|
break();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
all(fn: (&T) -> bool) -> bool {
|
||||||
|
let mut res = true;
|
||||||
|
|
||||||
|
self.each((item, break) -> {
|
||||||
|
if !fn(item) {
|
||||||
|
res = false;
|
||||||
|
break();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// map<S>(fn: (&T) -> &S) -> Collection<S>;
|
||||||
|
// filter(fn: (&T) -> bool) -> Collection<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Queue<T> : Collection<T> {
|
||||||
|
put(item: &T) -> void;
|
||||||
|
take() -> &T;
|
||||||
|
poll() -> &T?;
|
||||||
|
peek() -> &T?;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Stack<T> : Collection<T> {
|
||||||
|
push(item: &T) -> void;
|
||||||
|
pop() -> &T;
|
||||||
|
peek() -> &T?;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LinkedList<T> {
|
||||||
|
pub mut head: &T?;
|
||||||
|
pub mut tail: &LinkedList<T>?;
|
||||||
|
mut size: u64;
|
||||||
|
|
||||||
|
init() -> void {
|
||||||
|
self.head = null;
|
||||||
|
self.tail = null;
|
||||||
|
self.size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Collection<T> for LinkedList<T> {
|
||||||
|
add(item: &T) -> void {
|
||||||
|
if self.head == null {
|
||||||
|
self.head = item;
|
||||||
|
self.size = self.size + 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.tail == null {
|
||||||
|
self.tail = heap.new(LinkedList);
|
||||||
|
self.tail.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tail.add(item);
|
||||||
|
self.size = self.size + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(item: &T) -> void {
|
||||||
|
if self.head == null {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.head == item {
|
||||||
|
let next = self.tail;
|
||||||
|
if next != null {
|
||||||
|
self.head = self.tail.head;
|
||||||
|
self.tail = self.tail.tail;
|
||||||
|
heap.free(next);
|
||||||
|
} else {
|
||||||
|
self.head = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.size = self.size - 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tail.remove(item);
|
||||||
|
self.size = self.size - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
contains(item: &T) -> bool {
|
||||||
|
if self.head == null {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.head == item {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.tail.contains(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
size() -> u64 {
|
||||||
|
return self.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
each(fn: (item: &T, break: () -> void) -> void) -> void {
|
||||||
|
if self.head == null {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut continue = true;
|
||||||
|
fn(self.head, () -> { continue = false; });
|
||||||
|
|
||||||
|
if continue && self.tail != null {
|
||||||
|
self.tail.each(fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Queue<T> for LinkedList<T> {
|
||||||
|
put(item: &T) -> void = self.add(item);
|
||||||
|
|
||||||
|
take() -> &T {
|
||||||
|
if head == null {
|
||||||
|
// TODO: wait for item to be available
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let item = self.head;
|
||||||
|
self.remove(item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
poll() -> &T? {
|
||||||
|
if self.head == null {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let item = self.head;
|
||||||
|
self.remove(item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
peek() -> &T? = self.head;
|
||||||
|
}
|
25
examples/heap.plsm
Normal file
25
examples/heap.plsm
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
module memory/heap;
|
||||||
|
|
||||||
|
fun alloc(size: u64) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fun new(_struct: Struct) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fun memset(addr: &u8, count: u64, value: u8) {
|
||||||
|
let i = 0;
|
||||||
|
while (i < count) {
|
||||||
|
addr[i] = value;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Array<T> {
|
||||||
|
ptr: &T;
|
||||||
|
|
||||||
|
([])(index: u64) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,70 +0,0 @@
|
|||||||
module test;
|
|
||||||
|
|
||||||
import stdlib/io;
|
|
||||||
|
|
||||||
fun main -> {
|
|
||||||
io.println(foo() + 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Expr {
|
|
||||||
visit<T>(visitor: Visitor<T>): T;
|
|
||||||
}
|
|
||||||
|
|
||||||
trait ExprVisitor<T> {
|
|
||||||
visitString(string: String): T;
|
|
||||||
}
|
|
||||||
|
|
||||||
trait List<T : any> {
|
|
||||||
size: int;
|
|
||||||
get(index: int): T;
|
|
||||||
set(index: int, value: T): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LinkedList<T : any> {
|
|
||||||
head: T?;
|
|
||||||
tail: LinkedList<T>?;
|
|
||||||
|
|
||||||
init -> {
|
|
||||||
self.head = null;
|
|
||||||
self.tail = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl List<T> for LinkedList<T> {
|
|
||||||
size -> {
|
|
||||||
if self.head == null {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.tail == null {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1 + self.tail.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
get(index) -> {
|
|
||||||
if index == 0 {
|
|
||||||
return self.head;
|
|
||||||
}
|
|
||||||
|
|
||||||
return self.tail.get(index - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
set(index, value) -> {
|
|
||||||
if index == 0 {
|
|
||||||
self.head = value;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.tail == null {
|
|
||||||
raise StringError(
|
|
||||||
"LinkedList<T>.set(...): index out of bounds",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.tail.set(index - 1, value,);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun foo -> "Hello World!";
|
|
@ -84,15 +84,15 @@ innerStmt
|
|||||||
}
|
}
|
||||||
| varDecl { $ast = $varDecl.ast }
|
| varDecl { $ast = $varDecl.ast }
|
||||||
| returnStmt { $ast = $returnStmt.ast }
|
| returnStmt { $ast = $returnStmt.ast }
|
||||||
| raiseStmt { $ast = $raiseStmt.ast }
|
|
||||||
| ifStmt { $ast = $ifStmt.ast }
|
| ifStmt { $ast = $ifStmt.ast }
|
||||||
| whileStmt { $ast = $whileStmt.ast };
|
| whileStmt { $ast = $whileStmt.ast };
|
||||||
|
|
||||||
varDecl
|
varDecl
|
||||||
returns[AST.VarDecl ast = null as any]:
|
returns[AST.VarDecl ast = null as any]:
|
||||||
'let' (name = ID) (':' typeName)? '=' rval = expr ';' {
|
'let' mut = 'mut'? (name = ID) (':' typeName)? '=' rval = expr ';' {
|
||||||
$ast = new AST.VarDecl(
|
$ast = new AST.VarDecl(
|
||||||
this.getSourceRange($ctx),
|
this.getSourceRange($ctx),
|
||||||
|
!!$ctx._mut,
|
||||||
$name.text!,
|
$name.text!,
|
||||||
$ctx.typeName()?.ast ?? null,
|
$ctx.typeName()?.ast ?? null,
|
||||||
$rval.ast,
|
$rval.ast,
|
||||||
@ -101,10 +101,10 @@ varDecl
|
|||||||
|
|
||||||
funDecl
|
funDecl
|
||||||
returns[AST.FunDecl ast = null as any]:
|
returns[AST.FunDecl ast = null as any]:
|
||||||
'fun' name = ID (
|
pub = 'pub'? 'fun' name = ID (
|
||||||
'(' (params += funParam (',' params += funParam)* ','?)? ')'
|
'(' (params += funParam (',' params += funParam)* ','?)? ')'
|
||||||
)? (':' returnType = typeName)? '->' (
|
)? '->' returnTypeName = typeName '->' (
|
||||||
exprBody = expr ';'
|
'=' exprBody = expr ';'
|
||||||
| blockBody = block
|
| blockBody = block
|
||||||
) {
|
) {
|
||||||
let block: AST.Block;
|
let block: AST.Block;
|
||||||
@ -115,9 +115,10 @@ funDecl
|
|||||||
|
|
||||||
$ast = new AST.FunDecl(
|
$ast = new AST.FunDecl(
|
||||||
this.getSourceRange($ctx),
|
this.getSourceRange($ctx),
|
||||||
|
!!$ctx._pub,
|
||||||
$name.text!,
|
$name.text!,
|
||||||
$ctx._returnType?.ast ?? null,
|
|
||||||
$params.map(p => p.ast),
|
$params.map(p => p.ast),
|
||||||
|
$returnTypeName.ast,
|
||||||
block,
|
block,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -134,74 +135,72 @@ funParam
|
|||||||
|
|
||||||
structDecl
|
structDecl
|
||||||
returns[AST.StructDecl ast = null as any]:
|
returns[AST.StructDecl ast = null as any]:
|
||||||
'struct' name = ID (
|
pub = 'pub'? 'struct' name = ID (
|
||||||
'<' typeParams += structTypeParam (
|
'<' structTypeParams += ID (',' structTypeParams += ID)* '>'
|
||||||
',' typeParams += structTypeParam
|
)? '{' fields += memberField* methods += memberMethod* '}' {
|
||||||
)* '>'
|
|
||||||
)? '{' fields += structField* initializers += structInitializer* '}' {
|
|
||||||
$ast = new AST.StructDecl(
|
$ast = new AST.StructDecl(
|
||||||
this.getSourceRange($ctx),
|
this.getSourceRange($ctx),
|
||||||
|
!!$ctx._pub,
|
||||||
$name.text!,
|
$name.text!,
|
||||||
$typeParams.map(p => p.ast),
|
$structTypeParams.map(p => p.text),
|
||||||
$fields.map(f => f.ast),
|
$fields.map(field => field.ast),
|
||||||
$initializers.map(i => i.ast),
|
$methods.map(method => method.ast),
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
structField
|
|
||||||
returns[AST.StructField ast = null as any]:
|
|
||||||
name = ID ':' typeName ';' {
|
|
||||||
$ast = new AST.StructField(
|
|
||||||
this.getSourceRange($ctx),
|
|
||||||
$name.text!,
|
|
||||||
$typeName.ast,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
structInitializer
|
|
||||||
returns[AST.StructInitializer ast = null as any]:
|
|
||||||
'init' (
|
|
||||||
'(' (params += funParam (',' params += funParam)* ','?)? ')'
|
|
||||||
)? '->' body = block {
|
|
||||||
$ast = new AST.StructInitializer(
|
|
||||||
this.getSourceRange($ctx),
|
|
||||||
$params.map(p => p.ast),
|
|
||||||
$body.ast,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
structTypeParam
|
|
||||||
returns[AST.StructTypeParam ast = null as any]:
|
|
||||||
name = ID (':' bound = typeName)? {
|
|
||||||
$ast = new AST.StructTypeParam(
|
|
||||||
this.getSourceRange($ctx),
|
|
||||||
$name.text!,
|
|
||||||
$ctx._bound?.ast ?? null,
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
traitDecl
|
traitDecl
|
||||||
returns[AST.TraitDecl ast = null as any]:
|
returns[AST.TraitDecl ast = null as any]:
|
||||||
'trait' name = ID (
|
pub = 'pub'? 'trait' name = ID (
|
||||||
'<' typeParams += traitTypeParam (
|
'<' traitTypeParams += ID (',' traitTypeParams += ID)* '>'
|
||||||
',' typeParams += traitTypeParam
|
)? (
|
||||||
)* '>'
|
':' parents += namedOrGenericTypeName (
|
||||||
)? '{' attrs += traitAttr* '}' {
|
',' parents += namedOrGenericTypeName
|
||||||
|
)*
|
||||||
|
)? '{' methods += memberMethod* '}' {
|
||||||
$ast = new AST.TraitDecl(
|
$ast = new AST.TraitDecl(
|
||||||
this.getSourceRange($ctx),
|
this.getSourceRange($ctx),
|
||||||
|
!!$ctx._pub,
|
||||||
$name.text!,
|
$name.text!,
|
||||||
$typeParams.map(tp => tp.ast),
|
$traitTypeParams.map(tp => tp.text),
|
||||||
$attrs.map(attr => attr.ast),
|
$parents.map(parent => parent.ast),
|
||||||
|
$methods.map(method => method.ast),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
traitAttr
|
implDecl
|
||||||
returns[AST.TraitAttr ast = null as any]:
|
returns[AST.ImplDecl ast = null as any]:
|
||||||
isConst = 'const'? name = ID (
|
'impl' traitTypeName = namedOrGenericTypeName 'for' structName = qualifiedName (
|
||||||
'(' (params += funParam (',' params += funParam)* ','?)? ')'
|
'<' structTypeParams += ID (',' structTypeParams += ID)* '>'
|
||||||
)? ':' returnType = typeName (
|
)? '{' methods += memberMethod* '}' {
|
||||||
'->' (exprBody = expr ';' | blockBody = block)
|
$ast = new AST.ImplDecl(
|
||||||
| ';'
|
this.getSourceRange($ctx),
|
||||||
|
$traitTypeName.ast,
|
||||||
|
$structName.text!,
|
||||||
|
$structTypeParams.map(p => p.text),
|
||||||
|
$methods.map(method => method.ast),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
memberField
|
||||||
|
returns[AST.MemberField ast = null as any]:
|
||||||
|
pub = 'pub'? mut = 'mut'? name = ID ':' typeName ';' {
|
||||||
|
$ast = new AST.MemberField(
|
||||||
|
this.getSourceRange($ctx),
|
||||||
|
!!$ctx._pub,
|
||||||
|
!!$ctx._mut,
|
||||||
|
$name.text!,
|
||||||
|
$typeName.ast,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
memberMethod
|
||||||
|
returns[AST.MemberMethod ast = null as any]:
|
||||||
|
pub = 'pub'? name = ID '(' (
|
||||||
|
params += funParam (',' params += funParam)* ','?
|
||||||
|
)? ')' '->' returnTypeName = typeName (
|
||||||
|
';'
|
||||||
|
| blockBody = block
|
||||||
|
| '=' exprBody = expr ';'
|
||||||
) {
|
) {
|
||||||
let block: AST.Block | null = null;
|
let block: AST.Block | null = null;
|
||||||
if ($ctx._blockBody?.ast) block = $blockBody.ast;
|
if ($ctx._blockBody?.ast) block = $blockBody.ast;
|
||||||
@ -209,61 +208,12 @@ traitAttr
|
|||||||
new AST.ReturnStmt($exprBody.ast.sourceRange, $exprBody.ast),
|
new AST.ReturnStmt($exprBody.ast.sourceRange, $exprBody.ast),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$ast = new AST.TraitAttr(
|
$ast = new AST.MemberMethod(
|
||||||
this.getSourceRange($ctx),
|
this.getSourceRange($ctx),
|
||||||
!!$isConst.text,
|
!!$ctx._pub,
|
||||||
$name.text!,
|
$name.text!,
|
||||||
$params.map(p => p.ast),
|
$params.map(p => p.ast),
|
||||||
$returnType.ast,
|
$returnTypeName.ast,
|
||||||
block,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
traitTypeParam
|
|
||||||
returns[AST.TraitTypeParam ast = null as any]:
|
|
||||||
name = ID (':' bound = typeName)? {
|
|
||||||
$ast = new AST.TraitTypeParam(
|
|
||||||
this.getSourceRange($ctx),
|
|
||||||
$name.text!,
|
|
||||||
$ctx._bound?.ast ?? null,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
implDecl
|
|
||||||
returns[AST.ImplDecl ast = null as any]:
|
|
||||||
'impl' traitName = qualifiedName (
|
|
||||||
'<' traitTypeArgs += typeArg (
|
|
||||||
',' traitTypeArgs += typeArg
|
|
||||||
)* '>'
|
|
||||||
)? 'for' structName = qualifiedName (
|
|
||||||
'<' structTypeParams += ID (',' structTypeParams += ID)* '>'
|
|
||||||
)? '{' attrs += implAttr* '}' {
|
|
||||||
$ast = new AST.ImplDecl(
|
|
||||||
this.getSourceRange($ctx),
|
|
||||||
$traitName.text!,
|
|
||||||
$traitTypeArgs.map(arg => arg.ast),
|
|
||||||
$structName.text!,
|
|
||||||
$structTypeParams.map(p => p.text),
|
|
||||||
$attrs.map(attr => attr.ast),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
implAttr
|
|
||||||
returns[AST.ImplAttr ast = null as any]:
|
|
||||||
name = ID ('(' (params += ID (',' params += ID)* ','?)? ')')? '->' (
|
|
||||||
exprBody = expr ';'
|
|
||||||
| blockBody = block
|
|
||||||
) {
|
|
||||||
let block: AST.Block;
|
|
||||||
if ($ctx._blockBody?.ast) block = $blockBody.ast;
|
|
||||||
else block = new AST.Block($exprBody.ast.sourceRange, [
|
|
||||||
new AST.ReturnStmt($exprBody.ast.sourceRange, $exprBody.ast),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$ast = new AST.ImplAttr(
|
|
||||||
this.getSourceRange($ctx),
|
|
||||||
$name.text!,
|
|
||||||
$params.map(p => p.text),
|
|
||||||
block,
|
block,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -298,23 +248,25 @@ ifStmt
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
raiseStmt
|
|
||||||
returns[AST.RaiseStmt ast = null as any]:
|
|
||||||
'raise' value = expr ';' {
|
|
||||||
$ast = new AST.RaiseStmt(
|
|
||||||
this.getSourceRange($ctx),
|
|
||||||
$value.ast,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
expr
|
expr
|
||||||
returns[AST.Expr ast = null as any]:
|
returns[AST.Expr ast = null as any]:
|
||||||
name = qualifiedName { $ast = new AST.Identifier(this.getSourceRange($ctx), $name.name) }
|
name = qualifiedName {
|
||||||
| val = INT { $ast = new AST.IntExpr(this.getSourceRange($ctx), new Integer($val.text!)) }
|
$ast = new AST.Identifier(this.getSourceRange($ctx), $name.name);
|
||||||
| val = FLOAT { $ast = new AST.FloatExpr(this.getSourceRange($ctx), new Float($val.text!)) }
|
}
|
||||||
| val = STRING { $ast = new AST.StringExpr(this.getSourceRange($ctx), JSON.parse($val.text!)) }
|
| val = INT {
|
||||||
| lhs = expr op = BINOP rhs = expr {
|
$ast = new AST.IntExpr(this.getSourceRange($ctx), new Integer($val.text!));
|
||||||
$ast = new AST.BinExpr(this.getSourceRange($ctx), $op.text!, $lhs.ast, $rhs.ast) ;
|
}
|
||||||
|
| val = FLOAT {
|
||||||
|
$ast = new AST.FloatExpr(this.getSourceRange($ctx), new Float($val.text!));
|
||||||
|
}
|
||||||
|
| val = STRING {
|
||||||
|
$ast = new AST.StringExpr(this.getSourceRange($ctx), JSON.parse($val.text!));
|
||||||
|
}
|
||||||
|
| unop = UNOP value = expr {
|
||||||
|
$ast = new AST.UnExpr(this.getSourceRange($ctx), $unop.text!, $value.ast);
|
||||||
|
}
|
||||||
|
| lhs = expr binop rhs = expr {
|
||||||
|
$ast = new AST.BinExpr(this.getSourceRange($ctx), $binop.value, $lhs.ast, $rhs.ast);
|
||||||
}
|
}
|
||||||
| cond = expr '?' ifTrue = expr ':' ifFalse = expr {
|
| cond = expr '?' ifTrue = expr ':' ifFalse = expr {
|
||||||
$ast = new AST.CondExpr(this.getSourceRange($ctx), $cond.ast, $ifTrue.ast, $ifFalse.ast);
|
$ast = new AST.CondExpr(this.getSourceRange($ctx), $cond.ast, $ifTrue.ast, $ifFalse.ast);
|
||||||
@ -333,10 +285,9 @@ expr
|
|||||||
$rval.ast,
|
$rval.ast,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
| '(' (params += funParam (',' params += funParam)* ','?)? ')' '->' (
|
| '(' (
|
||||||
exprBody = expr
|
params += lambdaExprParam (',' params += lambdaExprParam)* ','?
|
||||||
| blockBody = block
|
)? ')' '->' (exprBody = expr | blockBody = block) {
|
||||||
) {
|
|
||||||
let block: AST.Block;
|
let block: AST.Block;
|
||||||
if ($ctx._blockBody?.ast) block = $blockBody.ast;
|
if ($ctx._blockBody?.ast) block = $blockBody.ast;
|
||||||
else block = new AST.Block($exprBody.ast.sourceRange, [
|
else block = new AST.Block($exprBody.ast.sourceRange, [
|
||||||
@ -351,35 +302,71 @@ expr
|
|||||||
}
|
}
|
||||||
| '(' expr ')' { $ast = $expr.ast };
|
| '(' expr ')' { $ast = $expr.ast };
|
||||||
|
|
||||||
|
lambdaExprParam
|
||||||
|
returns[AST.LambdaParam ast = null as any]:
|
||||||
|
name = ID (':' typeName)? {
|
||||||
|
$ast = new AST.LambdaParam(
|
||||||
|
this.getSourceRange($ctx),
|
||||||
|
$name.text!,
|
||||||
|
$ctx.typeName()?.ast ?? null,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
namedOrGenericTypeName
|
||||||
|
returns[(AST.NamedTypeName | AST.GenericTypeName) ast = null as any]:
|
||||||
|
namedTypeName { $ast = $namedTypeName.ast }
|
||||||
|
| genericTypeName { $ast = $genericTypeName.ast };
|
||||||
|
|
||||||
typeName
|
typeName
|
||||||
returns[AST.TypeName ast = null as any]:
|
returns[AST.TypeName ast = null as any]:
|
||||||
name = ID { $ast = new AST.NamedTypeName(this.getSourceRange($ctx), $name.text!) }
|
(
|
||||||
| name = ID '<' typeArgs += typeArg (',' typeArgs += typeArg)* '>' {
|
namedTypeName
|
||||||
|
| genericTypeName
|
||||||
|
| pointerTypeName
|
||||||
|
| nullableTypeName
|
||||||
|
| lambdaTypeName
|
||||||
|
) { $ast = ($ctx.getChild(0) as any).ast };
|
||||||
|
|
||||||
|
namedTypeName
|
||||||
|
returns[AST.NamedTypeName ast = null as any]:
|
||||||
|
name = ID {
|
||||||
|
$ast = new AST.NamedTypeName(
|
||||||
|
this.getSourceRange($ctx),
|
||||||
|
$name.text!,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
genericTypeName
|
||||||
|
returns[AST.GenericTypeName ast = null as any]:
|
||||||
|
name = ID '<' typeArgs += typeName (',' typeArgs += typeName)* '>' {
|
||||||
$ast = new AST.GenericTypeName(
|
$ast = new AST.GenericTypeName(
|
||||||
this.getSourceRange($ctx),
|
this.getSourceRange($ctx),
|
||||||
$name.text!,
|
$name.text!,
|
||||||
$typeArgs.map(arg => arg.ast),
|
$typeArgs.map(arg => arg.ast),
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
| type_ = typeName '?' {
|
|
||||||
|
pointerTypeName
|
||||||
|
returns[AST.PointerTypeName ast = null as any]:
|
||||||
|
'&' (namedTypeName | genericTypeName) {
|
||||||
|
$ast = new AST.PointerTypeName(
|
||||||
|
this.getSourceRange($ctx),
|
||||||
|
$ctx.namedTypeName()?.ast || $ctx.genericTypeName()?.ast,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
nullableTypeName
|
||||||
|
returns[AST.NullableTypeName ast = null as any]:
|
||||||
|
(pointerTypeName | lambdaTypeName) '?' {
|
||||||
$ast = new AST.NullableTypeName(
|
$ast = new AST.NullableTypeName(
|
||||||
this.getSourceRange($ctx),
|
this.getSourceRange($ctx),
|
||||||
$type_.ast,
|
$ctx.pointerTypeName()?.ast || $ctx.lambdaTypeName()?.ast,
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
| type_ = typeName '[' ']' {
|
|
||||||
$ast = new AST.ArrayTypeName(
|
lambdaTypeName
|
||||||
this.getSourceRange($ctx),
|
returns[AST.LambdaTypeName ast = null as any]:
|
||||||
$type_.ast,
|
'(' (
|
||||||
);
|
|
||||||
}
|
|
||||||
| '(' typeNames += typeName (',' typeNames += typeName)+ ','? ')' {
|
|
||||||
$ast = new AST.TupleTypeName(
|
|
||||||
this.getSourceRange($ctx),
|
|
||||||
$typeNames.map(typeName => typeName.ast),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
| '(' (
|
|
||||||
params += lambdaTypeNameParam (
|
params += lambdaTypeNameParam (
|
||||||
',' params += lambdaTypeNameParam
|
',' params += lambdaTypeNameParam
|
||||||
)* ','?
|
)* ','?
|
||||||
@ -393,8 +380,8 @@ typeName
|
|||||||
|
|
||||||
lambdaTypeNameParam
|
lambdaTypeNameParam
|
||||||
returns[[string | null, AST.TypeName] ast = null as any]:
|
returns[[string | null, AST.TypeName] ast = null as any]:
|
||||||
(name = ID ':')? type_ = typeName {
|
(name = ID ':')? typeName {
|
||||||
$ast = [$name.text ?? null, $type_.ast];
|
$ast = [$name.text ?? null, $ctx.typeName().ast];
|
||||||
};
|
};
|
||||||
|
|
||||||
typeArg
|
typeArg
|
||||||
@ -407,6 +394,12 @@ qualifiedName
|
|||||||
$name = $qualifiers.map(q => q.text);
|
$name = $qualifiers.map(q => q.text);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
binop
|
||||||
|
returns[string value = '']:
|
||||||
|
(BINOP | '<' | '>') { $value = $ctx.getText(); };
|
||||||
|
|
||||||
|
UNOP: '~' | '!';
|
||||||
|
|
||||||
BINOP:
|
BINOP:
|
||||||
'+'
|
'+'
|
||||||
| '-'
|
| '-'
|
||||||
@ -423,10 +416,9 @@ BINOP:
|
|||||||
| '??'
|
| '??'
|
||||||
| '**'
|
| '**'
|
||||||
| '=='
|
| '=='
|
||||||
|
| '!='
|
||||||
| '>='
|
| '>='
|
||||||
| '<='
|
| '<=';
|
||||||
| '>'
|
|
||||||
| '<';
|
|
||||||
|
|
||||||
FLOAT: ('+' | '-')? ([0-9]+ '.' [0-9]* | [0-9]* '.' [0-9]+);
|
FLOAT: ('+' | '-')? ([0-9]+ '.' [0-9]* | [0-9]* '.' [0-9]+);
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import type { Block } from "./block";
|
|||||||
import type { Expr } from "./expr";
|
import type { Expr } from "./expr";
|
||||||
import { Node, SourceRange } from "./node";
|
import { Node, SourceRange } from "./node";
|
||||||
import { Stmt } from "./stmt";
|
import { Stmt } from "./stmt";
|
||||||
import type { TypeName } from "./type-name";
|
import type { GenericTypeName, NamedTypeName, TypeName } from "./type-name";
|
||||||
import type { Visitor } from "./visitor";
|
import type { Visitor } from "./visitor";
|
||||||
|
|
||||||
export abstract class Decl extends Stmt { }
|
export abstract class Decl extends Stmt { }
|
||||||
@ -10,6 +10,7 @@ export abstract class Decl extends Stmt { }
|
|||||||
export class VarDecl extends Decl {
|
export class VarDecl extends Decl {
|
||||||
constructor(
|
constructor(
|
||||||
sourceRange: SourceRange,
|
sourceRange: SourceRange,
|
||||||
|
public isMut: boolean,
|
||||||
public name: string,
|
public name: string,
|
||||||
public typeName: TypeName | null,
|
public typeName: TypeName | null,
|
||||||
public value: Expr,
|
public value: Expr,
|
||||||
@ -23,9 +24,10 @@ export class VarDecl extends Decl {
|
|||||||
export class FunDecl extends Decl {
|
export class FunDecl extends Decl {
|
||||||
constructor(
|
constructor(
|
||||||
sourceRange: SourceRange,
|
sourceRange: SourceRange,
|
||||||
|
public isPub: boolean,
|
||||||
public name: string,
|
public name: string,
|
||||||
public returnTypeName: TypeName | null,
|
|
||||||
public params: FunParam[],
|
public params: FunParam[],
|
||||||
|
public returnTypeName: TypeName,
|
||||||
public body: Block,
|
public body: Block,
|
||||||
) { super(sourceRange); }
|
) { super(sourceRange); }
|
||||||
|
|
||||||
@ -49,9 +51,11 @@ export class FunParam extends Node {
|
|||||||
export class TraitDecl extends Decl {
|
export class TraitDecl extends Decl {
|
||||||
constructor(
|
constructor(
|
||||||
sourceRange: SourceRange,
|
sourceRange: SourceRange,
|
||||||
|
public isPub: boolean,
|
||||||
public name: string,
|
public name: string,
|
||||||
public typeParams: TraitTypeParam[],
|
public genericParams: string[],
|
||||||
public attrs: TraitAttr[],
|
public parents: (NamedTypeName | GenericTypeName)[],
|
||||||
|
public methods: MemberMethod[],
|
||||||
) { super(sourceRange); }
|
) { super(sourceRange); }
|
||||||
|
|
||||||
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
||||||
@ -59,41 +63,13 @@ export class TraitDecl extends Decl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TraitAttr extends Node {
|
|
||||||
constructor(
|
|
||||||
sourceRange: SourceRange,
|
|
||||||
public isConst: boolean,
|
|
||||||
public name: string,
|
|
||||||
public params: FunParam[],
|
|
||||||
public returnTypeName: TypeName,
|
|
||||||
public defaultBody: Block | null,
|
|
||||||
) { super(sourceRange); }
|
|
||||||
|
|
||||||
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
|
||||||
return visitor.visitTraitAttr(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class TraitTypeParam extends Node {
|
|
||||||
constructor(
|
|
||||||
sourceRange: SourceRange,
|
|
||||||
public name: string,
|
|
||||||
public bound: TypeName | null,
|
|
||||||
) { super(sourceRange); }
|
|
||||||
|
|
||||||
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
|
||||||
return visitor.visitTraitTypeParam(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ImplDecl extends Decl {
|
export class ImplDecl extends Decl {
|
||||||
constructor(
|
constructor(
|
||||||
sourceRange: SourceRange,
|
sourceRange: SourceRange,
|
||||||
public traitName: string,
|
public traitTypeName: NamedTypeName | GenericTypeName,
|
||||||
public traitTypeArgs: TypeName[],
|
|
||||||
public structName: string,
|
public structName: string,
|
||||||
public structTypeParams: string[],
|
public structGenericParams: string[],
|
||||||
public attrs: ImplAttr[],
|
public methods: MemberMethod[],
|
||||||
) { super(sourceRange); }
|
) { super(sourceRange); }
|
||||||
|
|
||||||
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
||||||
@ -101,26 +77,14 @@ export class ImplDecl extends Decl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ImplAttr extends Decl {
|
|
||||||
constructor(
|
|
||||||
sourceRange: SourceRange,
|
|
||||||
public name: string,
|
|
||||||
public paramNames: string[],
|
|
||||||
public body: Block,
|
|
||||||
) { super(sourceRange); }
|
|
||||||
|
|
||||||
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
|
||||||
return visitor.visitImplAttr(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class StructDecl extends Decl {
|
export class StructDecl extends Decl {
|
||||||
constructor(
|
constructor(
|
||||||
sourceRange: SourceRange,
|
sourceRange: SourceRange,
|
||||||
|
public isPub: boolean,
|
||||||
public name: string,
|
public name: string,
|
||||||
public typeParams: StructTypeParam[],
|
public genericParams: string[],
|
||||||
public fields: StructField[],
|
public fields: MemberField[],
|
||||||
public initializers: StructInitializer[],
|
public methods: MemberMethod[],
|
||||||
) { super(sourceRange); }
|
) { super(sourceRange); }
|
||||||
|
|
||||||
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
||||||
@ -128,38 +92,31 @@ export class StructDecl extends Decl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StructField extends Node {
|
export class MemberField extends Node {
|
||||||
constructor(
|
constructor(
|
||||||
sourceRange: SourceRange,
|
sourceRange: SourceRange,
|
||||||
|
public isPub: boolean,
|
||||||
|
public isMut: boolean,
|
||||||
public name: string,
|
public name: string,
|
||||||
public typeName: TypeName,
|
public typeName: TypeName,
|
||||||
) { super(sourceRange); }
|
) { super(sourceRange); }
|
||||||
|
|
||||||
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
||||||
return visitor.visitStructField(this);
|
return visitor.visitMemberField(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StructInitializer extends Node {
|
export class MemberMethod extends Node {
|
||||||
constructor(
|
|
||||||
sourceRange: SourceRange,
|
|
||||||
public params: FunParam[],
|
|
||||||
public body: Block,
|
|
||||||
) { super(sourceRange); }
|
|
||||||
|
|
||||||
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
|
||||||
return visitor.visitStructInitializer(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class StructTypeParam extends Node {
|
|
||||||
constructor(
|
constructor(
|
||||||
sourceRange: SourceRange,
|
sourceRange: SourceRange,
|
||||||
|
public isPub: boolean,
|
||||||
public name: string,
|
public name: string,
|
||||||
public bound: TypeName | null,
|
public params: FunParam[],
|
||||||
|
public returnTypeName: TypeName,
|
||||||
|
public body: Block | null,
|
||||||
) { super(sourceRange); }
|
) { super(sourceRange); }
|
||||||
|
|
||||||
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
||||||
return visitor.visitStructTypeParam(this);
|
return visitor.visitMemberMethod(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import type { Visitor } from "./visitor";
|
|||||||
import type { FunParam } from "./decl";
|
import type { FunParam } from "./decl";
|
||||||
import type { Block } from "./block";
|
import type { Block } from "./block";
|
||||||
import type { Float, Integer } from "~/const";
|
import type { Float, Integer } from "~/const";
|
||||||
|
import type { TypeName } from "./type-name";
|
||||||
|
|
||||||
export abstract class Expr extends Node { }
|
export abstract class Expr extends Node { }
|
||||||
|
|
||||||
@ -46,6 +47,17 @@ export class StringExpr extends Expr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class UnExpr extends Expr {
|
||||||
|
constructor(
|
||||||
|
sourceRange: SourceRange,
|
||||||
|
public op: string,
|
||||||
|
public value: Expr,
|
||||||
|
) { super(sourceRange); }
|
||||||
|
|
||||||
|
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
||||||
|
return visitor.visitUnExpr(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class BinExpr extends Expr {
|
export class BinExpr extends Expr {
|
||||||
constructor(
|
constructor(
|
||||||
@ -88,7 +100,7 @@ export class CondExpr extends Expr {
|
|||||||
export class LambdaExpr extends Expr {
|
export class LambdaExpr extends Expr {
|
||||||
constructor(
|
constructor(
|
||||||
sourceRange: SourceRange,
|
sourceRange: SourceRange,
|
||||||
public params: FunParam[],
|
public params: LambdaParam[],
|
||||||
public body: Block,
|
public body: Block,
|
||||||
) { super(sourceRange); }
|
) { super(sourceRange); }
|
||||||
|
|
||||||
@ -97,6 +109,18 @@ export class LambdaExpr extends Expr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class LambdaParam extends Node {
|
||||||
|
constructor(
|
||||||
|
sourceRange: SourceRange,
|
||||||
|
public name: string,
|
||||||
|
public typeName: TypeName | null,
|
||||||
|
) { super(sourceRange); }
|
||||||
|
|
||||||
|
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
||||||
|
return visitor.visitLambdaParam(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class AssignExpr extends Expr {
|
export class AssignExpr extends Expr {
|
||||||
constructor(
|
constructor(
|
||||||
sourceRange: SourceRange,
|
sourceRange: SourceRange,
|
||||||
|
@ -50,14 +50,3 @@ export class WhileStmt extends Stmt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RaiseStmt extends Stmt {
|
|
||||||
constructor(
|
|
||||||
sourceRange: SourceRange,
|
|
||||||
public value: Expr
|
|
||||||
) { super(sourceRange); }
|
|
||||||
|
|
||||||
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
|
||||||
return visitor.visitRaiseStmt(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import type { Expr } from "./expr";
|
|
||||||
import { Node, SourceRange } from "./node";
|
import { Node, SourceRange } from "./node";
|
||||||
import type { Visitor } from "./visitor";
|
import type { Visitor } from "./visitor";
|
||||||
|
|
||||||
@ -38,14 +37,14 @@ export class NullableTypeName extends TypeName {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ArrayTypeName extends TypeName {
|
export class PointerTypeName extends TypeName {
|
||||||
constructor(
|
constructor(
|
||||||
sourceRange: SourceRange,
|
sourceRange: SourceRange,
|
||||||
public typeName: TypeName,
|
public typeName: TypeName,
|
||||||
) { super(sourceRange); }
|
) { super(sourceRange); }
|
||||||
|
|
||||||
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
accept<ResultT>(visitor: Visitor<ResultT>): ResultT {
|
||||||
return visitor.visitArrayTypeName(this);
|
return visitor.visitPointerTypeName(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import type { Block } from "./block";
|
import type { Block } from "./block";
|
||||||
import type { FunDecl, FunParam, ImplAttr, ImplDecl, StructDecl, StructField, StructInitializer, StructTypeParam, TraitAttr, TraitDecl, TraitTypeParam, VarDecl } from "./decl";
|
import type { FunDecl, FunParam, ImplDecl, MemberField, MemberMethod, StructDecl, TraitDecl, VarDecl } from "./decl";
|
||||||
import type { AssignExpr, BinExpr, CallExpr, CondExpr, FloatExpr, Identifier, IntExpr, LambdaExpr, StringExpr } from "./expr";
|
import type { AssignExpr, BinExpr, CallExpr, CondExpr, FloatExpr, Identifier, IntExpr, LambdaExpr, LambdaParam, StringExpr, UnExpr } from "./expr";
|
||||||
import type { ImportStmt, Module, ModuleDecl } from "./module";
|
import type { ImportStmt, Module, ModuleDecl } from "./module";
|
||||||
import { IfStmt, RaiseStmt, ReturnStmt, WhileStmt, type ExprStmt } from "./stmt";
|
import type { IfStmt, ReturnStmt, WhileStmt, ExprStmt } from "./stmt";
|
||||||
import type { ArrayTypeName, GenericTypeName, LambdaTypeName, NamedTypeName, NullableTypeName, TupleTypeName } from "./type-name";
|
import type { GenericTypeName, LambdaTypeName, NamedTypeName, NullableTypeName, PointerTypeName, TupleTypeName } from "./type-name";
|
||||||
|
|
||||||
export abstract class Visitor<ResultT = any> {
|
export abstract class Visitor<ResultT = any> {
|
||||||
public abstract visitModule(module_: Module): ResultT;
|
public abstract visitModule(module_: Module): ResultT;
|
||||||
@ -15,40 +15,38 @@ export abstract class Visitor<ResultT = any> {
|
|||||||
public abstract visitReturnStmt(returnStmt: ReturnStmt): ResultT;
|
public abstract visitReturnStmt(returnStmt: ReturnStmt): ResultT;
|
||||||
public abstract visitIfStmt(ifStmt: IfStmt): ResultT;
|
public abstract visitIfStmt(ifStmt: IfStmt): ResultT;
|
||||||
public abstract visitWhileStmt(whileStmt: WhileStmt): ResultT;
|
public abstract visitWhileStmt(whileStmt: WhileStmt): ResultT;
|
||||||
public abstract visitRaiseStmt(raiseStmt: RaiseStmt): ResultT;
|
|
||||||
|
|
||||||
public abstract visitVarDecl(varDecl: VarDecl): ResultT;
|
public abstract visitVarDecl(varDecl: VarDecl): ResultT;
|
||||||
public abstract visitFunDecl(funDecl: FunDecl): ResultT;
|
public abstract visitFunDecl(funDecl: FunDecl): ResultT;
|
||||||
public abstract visitFunParam(funParam: FunParam): ResultT;
|
public abstract visitFunParam(funParam: FunParam): ResultT;
|
||||||
public abstract visitTraitDecl(traitDecl: TraitDecl): ResultT;
|
public abstract visitTraitDecl(traitDecl: TraitDecl): ResultT;
|
||||||
public abstract visitTraitAttr(traitAttr: TraitAttr): ResultT;
|
|
||||||
public abstract visitTraitTypeParam(traitTypeParam: TraitTypeParam): ResultT;
|
|
||||||
public abstract visitImplDecl(implDecl: ImplDecl): ResultT;
|
public abstract visitImplDecl(implDecl: ImplDecl): ResultT;
|
||||||
public abstract visitImplAttr(implAttr: ImplAttr): ResultT;
|
|
||||||
public abstract visitStructDecl(structDecl: StructDecl): ResultT;
|
public abstract visitStructDecl(structDecl: StructDecl): ResultT;
|
||||||
public abstract visitStructField(structField: StructField): ResultT;
|
public abstract visitMemberField(memberField: MemberField): ResultT;
|
||||||
public abstract visitStructTypeParam(structTypeParam: StructTypeParam): ResultT;
|
public abstract visitMemberMethod(memberMethod: MemberMethod): ResultT;
|
||||||
public abstract visitStructInitializer(structInitializer: StructInitializer): ResultT;
|
|
||||||
|
|
||||||
public abstract visitIdentifier(identifier: Identifier): ResultT;
|
public abstract visitIdentifier(identifier: Identifier): ResultT;
|
||||||
public abstract visitIntExpr(intExpr: IntExpr): ResultT;
|
public abstract visitIntExpr(intExpr: IntExpr): ResultT;
|
||||||
public abstract visitFloatExpr(floatExpr: FloatExpr): ResultT;
|
public abstract visitFloatExpr(floatExpr: FloatExpr): ResultT;
|
||||||
public abstract visitStringExpr(stringExpr: StringExpr): ResultT;
|
public abstract visitStringExpr(stringExpr: StringExpr): ResultT;
|
||||||
|
public abstract visitUnExpr(unExpr: UnExpr): ResultT;
|
||||||
public abstract visitBinExpr(binExpr: BinExpr): ResultT;
|
public abstract visitBinExpr(binExpr: BinExpr): ResultT;
|
||||||
public abstract visitCallExpr(callExpr: CallExpr): ResultT;
|
public abstract visitCallExpr(callExpr: CallExpr): ResultT;
|
||||||
public abstract visitCondExpr(condExpr: CondExpr): ResultT;
|
public abstract visitCondExpr(condExpr: CondExpr): ResultT;
|
||||||
public abstract visitLambdaExpr(lambdaExpr: LambdaExpr): ResultT;
|
public abstract visitLambdaExpr(lambdaExpr: LambdaExpr): ResultT;
|
||||||
|
public abstract visitLambdaParam(lambdaParam: LambdaParam): ResultT;
|
||||||
public abstract visitAssignExpr(assignExpr: AssignExpr): ResultT;
|
public abstract visitAssignExpr(assignExpr: AssignExpr): ResultT;
|
||||||
|
|
||||||
public abstract visitNamedTypeName(namedTypeName: NamedTypeName): ResultT;
|
public abstract visitNamedTypeName(namedTypeName: NamedTypeName): ResultT;
|
||||||
public abstract visitGenericTypeName(genericTypeName: GenericTypeName): ResultT;
|
public abstract visitGenericTypeName(genericTypeName: GenericTypeName): ResultT;
|
||||||
public abstract visitNullableTypeName(nullableTypeName: NullableTypeName): ResultT;
|
public abstract visitNullableTypeName(nullableTypeName: NullableTypeName): ResultT;
|
||||||
public abstract visitArrayTypeName(arrayTypeName: ArrayTypeName): ResultT;
|
public abstract visitPointerTypeName(pointerTypeName: PointerTypeName): ResultT;
|
||||||
public abstract visitTupleTypeName(tupleTypeName: TupleTypeName): ResultT;
|
public abstract visitTupleTypeName(tupleTypeName: TupleTypeName): ResultT;
|
||||||
public abstract visitLambdaTypeName(lambdaTypeName: LambdaTypeName): ResultT;
|
public abstract visitLambdaTypeName(lambdaTypeName: LambdaTypeName): ResultT;
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class BaseVisitor<ResultT = any> implements Visitor<ResultT> {
|
export class BaseVisitor<ResultT = any> implements Visitor<ResultT> {
|
||||||
public visitModule(module_: Module): ResultT {
|
public visitModule(module_: Module): ResultT {
|
||||||
module_.imports.forEach((import_) => import_.accept(this));
|
module_.imports.forEach((import_) => import_.accept(this));
|
||||||
module_.decls.forEach((decl) => decl.accept(this));
|
module_.decls.forEach((decl) => decl.accept(this));
|
||||||
@ -91,11 +89,6 @@ export abstract class BaseVisitor<ResultT = any> implements Visitor<ResultT> {
|
|||||||
return null as any;
|
return null as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
public visitRaiseStmt(raiseStmt: RaiseStmt): ResultT {
|
|
||||||
raiseStmt.value.accept(this);
|
|
||||||
return null as any;
|
|
||||||
}
|
|
||||||
|
|
||||||
public visitVarDecl(varDecl: VarDecl): ResultT {
|
public visitVarDecl(varDecl: VarDecl): ResultT {
|
||||||
varDecl.typeName?.accept(this);
|
varDecl.typeName?.accept(this);
|
||||||
varDecl.value.accept(this);
|
varDecl.value.accept(this);
|
||||||
@ -115,53 +108,30 @@ export abstract class BaseVisitor<ResultT = any> implements Visitor<ResultT> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public visitTraitDecl(traitDecl: TraitDecl): ResultT {
|
public visitTraitDecl(traitDecl: TraitDecl): ResultT {
|
||||||
traitDecl.typeParams.forEach((typeParam) => typeParam.accept(this));
|
traitDecl.methods.forEach((method) => method.accept(this));
|
||||||
traitDecl.attrs.forEach((attr) => attr.accept(this));
|
|
||||||
return null as any;
|
|
||||||
}
|
|
||||||
|
|
||||||
public visitTraitAttr(traitAttr: TraitAttr): ResultT {
|
|
||||||
traitAttr.params.forEach((param) => param.accept(this));
|
|
||||||
traitAttr.returnTypeName.accept(this);
|
|
||||||
traitAttr.defaultBody?.accept(this);
|
|
||||||
return null as any;
|
|
||||||
}
|
|
||||||
|
|
||||||
public visitTraitTypeParam(traitTypeParam: TraitTypeParam): ResultT {
|
|
||||||
traitTypeParam.bound?.accept(this);
|
|
||||||
return null as any;
|
return null as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
public visitImplDecl(implDecl: ImplDecl): ResultT {
|
public visitImplDecl(implDecl: ImplDecl): ResultT {
|
||||||
implDecl.traitTypeArgs.forEach((traitTypeArg) => traitTypeArg.accept(this));
|
implDecl.methods.forEach((attr) => attr.accept(this));
|
||||||
implDecl.attrs.forEach((attr) => attr.accept(this));
|
|
||||||
return null as any;
|
|
||||||
}
|
|
||||||
|
|
||||||
public visitImplAttr(implAttr: ImplAttr): ResultT {
|
|
||||||
implAttr.body.accept(this);
|
|
||||||
return null as any;
|
return null as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
public visitStructDecl(structDecl: StructDecl): ResultT {
|
public visitStructDecl(structDecl: StructDecl): ResultT {
|
||||||
structDecl.typeParams.forEach((typeParam) => typeParam.accept(this));
|
|
||||||
structDecl.fields.forEach((field) => field.accept(this));
|
structDecl.fields.forEach((field) => field.accept(this));
|
||||||
|
structDecl.methods.forEach((method) => method.accept(this));
|
||||||
return null as any;
|
return null as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
public visitStructTypeParam(structTypeParam: StructTypeParam): ResultT {
|
public visitMemberField(memberField: MemberField): ResultT {
|
||||||
structTypeParam.bound?.accept(this);
|
memberField.typeName.accept(this);
|
||||||
return null as any;
|
return null as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
public visitStructField(structField: StructField): ResultT {
|
public visitMemberMethod(memberMethod: MemberMethod): ResultT {
|
||||||
structField.typeName.accept(this);
|
memberMethod.params.forEach((param) => param.accept(this));
|
||||||
return null as any;
|
memberMethod.returnTypeName?.accept(this);
|
||||||
}
|
memberMethod.body?.accept(this);
|
||||||
|
|
||||||
public visitStructInitializer(structInitializer: StructInitializer): ResultT {
|
|
||||||
structInitializer.params.forEach((param) => param.accept(this));
|
|
||||||
structInitializer.body.accept(this);
|
|
||||||
return null as any;
|
return null as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,6 +151,11 @@ export abstract class BaseVisitor<ResultT = any> implements Visitor<ResultT> {
|
|||||||
return null as any;
|
return null as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public visitUnExpr(unExpr: UnExpr): ResultT {
|
||||||
|
unExpr.value.accept(this);
|
||||||
|
return null as any;
|
||||||
|
}
|
||||||
|
|
||||||
public visitBinExpr(binExpr: BinExpr): ResultT {
|
public visitBinExpr(binExpr: BinExpr): ResultT {
|
||||||
binExpr.lhs.accept(this);
|
binExpr.lhs.accept(this);
|
||||||
binExpr.rhs.accept(this);
|
binExpr.rhs.accept(this);
|
||||||
@ -206,6 +181,11 @@ export abstract class BaseVisitor<ResultT = any> implements Visitor<ResultT> {
|
|||||||
return null as any;
|
return null as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public visitLambdaParam(lambdaParam: LambdaParam): ResultT {
|
||||||
|
lambdaParam.typeName?.accept(this);
|
||||||
|
return null as any;
|
||||||
|
}
|
||||||
|
|
||||||
public visitAssignExpr(assignExpr: AssignExpr): ResultT {
|
public visitAssignExpr(assignExpr: AssignExpr): ResultT {
|
||||||
assignExpr.lval.accept(this);
|
assignExpr.lval.accept(this);
|
||||||
assignExpr.rval.accept(this);
|
assignExpr.rval.accept(this);
|
||||||
@ -226,8 +206,8 @@ export abstract class BaseVisitor<ResultT = any> implements Visitor<ResultT> {
|
|||||||
return null as any;
|
return null as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
public visitArrayTypeName(arrayTypeName: ArrayTypeName): ResultT {
|
public visitPointerTypeName(pointerTypeName: PointerTypeName): ResultT {
|
||||||
arrayTypeName.typeName.accept(this);
|
pointerTypeName.typeName.accept(this);
|
||||||
return null as any;
|
return null as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
import type { Type } from "./type";
|
||||||
|
|
||||||
|
export class Symbol {
|
||||||
|
constructor(
|
||||||
|
public name: string,
|
||||||
|
public type: Type,
|
||||||
|
) { }
|
||||||
|
}
|
@ -1,8 +1,10 @@
|
|||||||
import { inspect } from "bun";
|
import { inspect } from "bun";
|
||||||
import { parseModule } from "./parser";
|
import { parseModule } from "./parser";
|
||||||
import { printErrors } from "./errors";
|
import { hasErrors, printErrors } from "./errors";
|
||||||
|
import AST from "./frontend/ast";
|
||||||
|
|
||||||
const module = parseModule('examples/test.plsm');
|
const module = parseModule('examples/LinkedList.plsm');
|
||||||
console.log(inspect(module, { depth: 1000, colors: false }));
|
console.log(inspect(module, { depth: 1000, colors: false }));
|
||||||
|
|
||||||
printErrors();
|
printErrors();
|
||||||
|
module.accept(new AST.BaseVisitor());
|
Loading…
x
Reference in New Issue
Block a user