This commit is contained in:
parent
21e569e9ff
commit
6620dbcace
@ -80,6 +80,8 @@ export class Node {
|
||||
return visit();
|
||||
case "IntExpr":
|
||||
return visit();
|
||||
case "ArrayExpr":
|
||||
return visit(...k.values);
|
||||
case "CallExpr":
|
||||
return visit(k.expr, ...k.args);
|
||||
case "UnaryExpr":
|
||||
@ -115,6 +117,7 @@ export type NodeKind =
|
||||
| { tag: "Param"; ident: string; ty: Node | null }
|
||||
| { tag: "IdentExpr"; ident: string }
|
||||
| { tag: "IntExpr"; value: number }
|
||||
| { tag: "ArrayExpr"; values: Node[] }
|
||||
| { tag: "CallExpr"; expr: Node; args: Node[] }
|
||||
| { tag: "UnaryExpr"; op: UnaryOp; expr: Node; tok: string }
|
||||
| { tag: "BinaryExpr"; op: BinaryOp; left: Node; right: Node; tok: string }
|
||||
|
||||
@ -80,6 +80,24 @@ export class Checker {
|
||||
return Ty.Int;
|
||||
}
|
||||
|
||||
if (node.is("ArrayExpr")) {
|
||||
let ty: Ty | null = null;
|
||||
for (const value of node.kind.values) {
|
||||
const valueTy = this.check(value);
|
||||
if (ty) {
|
||||
this.assertCompatible(ty, valueTy, value.line);
|
||||
} else {
|
||||
ty = valueTy;
|
||||
}
|
||||
}
|
||||
if (!ty) {
|
||||
this.error(node.line, `could not infer type of empty array`);
|
||||
this.fail();
|
||||
}
|
||||
const length = node.kind.values.length;
|
||||
return Ty.create("Array", { ty, length });
|
||||
}
|
||||
|
||||
if (node.is("CallExpr")) {
|
||||
return this.checkCall(node);
|
||||
}
|
||||
|
||||
@ -240,6 +240,19 @@ export class Parser {
|
||||
const expr = this.parseExpr();
|
||||
this.mustEat(")");
|
||||
return expr;
|
||||
} else if (this.eat("[")) {
|
||||
const values: ast.Node[] = [];
|
||||
if (!this.done && !this.test("]")) {
|
||||
values.push(this.parseExpr());
|
||||
while (this.eat(",")) {
|
||||
if (this.test("]")) {
|
||||
break;
|
||||
}
|
||||
values.push(this.parseExpr());
|
||||
}
|
||||
}
|
||||
this.mustEat("]");
|
||||
return ast.Node.create(loc, "ArrayExpr", { values });
|
||||
} else {
|
||||
this.mustEat("<expression>");
|
||||
throw new Error();
|
||||
@ -318,7 +331,7 @@ export type Tok = { type: string; value: string; line: number };
|
||||
const keywordPattern =
|
||||
/^(?:fn)|(?:return)|(?:let)|(?:if)|(?:else)|(?:while)|(?:break)|(?:or)|(?:and)|(?:not)|(?:mut)$/;
|
||||
const operatorPattern =
|
||||
/((?:\->)|(?:==)|(?:!=)|(?:<=)|(?:>=)|(?:<<)|(?:>>)|[\n\(\)\{\}\,\.\;\:\!\=\<\>\&\^\|\+\-\*\/\%])/g;
|
||||
/((?:\->)|(?:==)|(?:!=)|(?:<=)|(?:>=)|(?:<<)|(?:>>)|[\n\(\)\{\}\[\]\,\.\;\:\!\=\<\>\&\^\|\+\-\*\/\%])/g;
|
||||
|
||||
export function tokenize(text: string): Tok[] {
|
||||
return text
|
||||
|
||||
@ -132,5 +132,6 @@ export type TyKind =
|
||||
| { tag: "Bool" }
|
||||
| { tag: "Ptr"; ty: Ty }
|
||||
| { tag: "PtrMut"; ty: Ty }
|
||||
| { tag: "Array"; ty: Ty; length: number }
|
||||
| { tag: "Fn"; params: Ty[]; retTy: Ty }
|
||||
| { tag: "FnStmt"; ty: Ty; stmt: ast.NodeWithKind<"FnStmt"> };
|
||||
|
||||
6
tests/_array.ethlang
Normal file
6
tests/_array.ethlang
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
fn main()
|
||||
{
|
||||
let array = [1, 2, 3];
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ set -e
|
||||
TEST_DIR=$(dirname $0)
|
||||
SRC_DIR=$TEST_DIR/../src
|
||||
|
||||
TEST_SRC=$(find $TEST_DIR -name '*.ethlang')
|
||||
TEST_SRC=$(find $TEST_DIR -name '*.ethlang' -and -not -name "_*")
|
||||
|
||||
count_total=0
|
||||
count_succeeded=0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user