Skip to content

Commit

Permalink
[funexprs] Use fun keyword for function expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
titzer committed Aug 5, 2024
2 parents 20d552e + fc22a6d commit e77f1f4
Show file tree
Hide file tree
Showing 118 changed files with 117 additions and 104 deletions.
2 changes: 1 addition & 1 deletion aeneas/src/main/CLOptions.v3
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ component CLOptions {
"Enable read-only arrays and ranges for the Virgil language.");
def LEGACY_INFER = langOpt.newBoolOption("legacy-infer", true,
"Enable legacy type inference algorithm for the Virgil language.");
def FUNC_EXPRS = langOpt.newBoolOption("func-exprs", false,
def FUN_EXPRS = langOpt.newBoolOption("fun-exprs", false,
"Enable function expressions for the Virgil language.");
def OPT = sharedOpt.newStringOption("opt", null,
"Set optimization configuration options.");
Expand Down
2 changes: 1 addition & 1 deletion aeneas/src/main/Version.v3
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@

// Updated by VCS scripts. DO NOT EDIT.
component Version {
def version: string = "III-7.1753";
def version: string = "III-7.1754";
var buildData: string;
}
4 changes: 2 additions & 2 deletions aeneas/src/ssa/VstSsaGen.v3
Original file line number Diff line number Diff line change
Expand Up @@ -1184,8 +1184,8 @@ class VstSsaGen extends VstVisitor<VstSsaEnv, SsaInstr> {
}
return graph.nop(); // neither fell through
}
def visitFuncExpr(expr: FuncExpr, env: VstSsaEnv) -> SsaInstr {
context.fail("unimplemented in VstSsaGen.visitFuncExpr()");
def visitFunExpr(expr: FunExpr, env: VstSsaEnv) -> SsaInstr {
context.fail("unimplemented in VstSsaGen.visitFunExpr()");
return graph.nullConst(expr.exactType);
}

Expand Down
11 changes: 6 additions & 5 deletions aeneas/src/vst/Parser.v3
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ component Keywords {
("extends", KC_OTHER),
("false", KC_FALSE),
("for", KC_OTHER),
("fun", KC_OTHER),
("if", KC_OTHER),
("import", KC_OTHER),
("in", KC_OTHER),
Expand Down Expand Up @@ -98,7 +99,7 @@ component Parser {
def parseFile(fileName: string, input: Array<byte>, ERROR: ErrorGen, typeCache: TypeCache) -> VstFile {
var file = VstFile.new(fileName, input);
var p = ParserState.new(file, ERROR, skipToNextToken, typeCache);
p.enableFuncExprs = CLOptions.FUNC_EXPRS.get();
p.enableFunExprs = CLOptions.FUN_EXPRS.get();

file.input = input;
file.lineEnds = p.lineEnds;
Expand Down Expand Up @@ -793,7 +794,7 @@ component Parser {
if (p.curByte == '(') { // nested function
var params = parseTypedMethodParams(p);
var t = parseReturnTypeAndBody(p, true);
var init = FuncExpr.new(start, id.name, params, t.0, t.1);
var init = FunExpr.new(start, id.name, params, t.0, t.1);
var v = VarDecl.new(id.name, null, init);
return LocalStmt.new(start, List.new(v, null));
}
Expand Down Expand Up @@ -846,13 +847,13 @@ component Parser {
}
return parseVarExpr(p);
}
if (p.enableFuncExprs && ch == 'd') {
var start = optKeyword(p, "def");
if (p.enableFunExprs && ch == 'f') {
var start = optKeyword(p, "fun");
if (start != null) {
var id = if(Char.isIdentStart(p.curByte), parseIdentVoid(p).name);
var params = parseMethodParams(p);
var t = parseReturnTypeAndBody(p, false);
return FuncExpr.new(start, id, params, t.0, t.1);
return FunExpr.new(start, id, params, t.0, t.1);
}
return parseVarExpr(p);
}
Expand Down
2 changes: 1 addition & 1 deletion aeneas/src/vst/ParserState.v3
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ParserState {
def typeCache: TypeCache; // typeCache; TODO: V3-specific
def ERROR: ErrorGen; // the error generator
var errors: List<int>; // errors generated so far
var enableFuncExprs: bool; // enable function expression parsing
var enableFunExprs: bool; // enable function expression parsing

new(file, ERROR, skipFunc, typeCache) {
reset();
Expand Down
14 changes: 7 additions & 7 deletions aeneas/src/vst/Verifier.v3
Original file line number Diff line number Diff line change
Expand Up @@ -1902,7 +1902,7 @@ class TypeChecker(ERROR: ErrorGen, file: VstFile) extends VstVisitor<Type, Type>
return atype;
}
}
def visitFuncExpr(expr: FuncExpr, outer: Type) -> Type {
def visitFunExpr(expr: FunExpr, outer: Type) -> Type {
var pl: List<Type>;
if (FuncType.?(outer)) {
var el = Function.getParamTypeList(outer);
Expand Down Expand Up @@ -1930,25 +1930,25 @@ class TypeChecker(ERROR: ErrorGen, file: VstFile) extends VstVisitor<Type, Type>
var rt: Type;
match (expr.rettype) {
Void => {
rt = typeCheckFuncExprBody(expr.body, Void.TYPE);
rt = typeCheckFunExprBody(expr.body, Void.TYPE);
}
This => {
rt = typeCheckFuncExprBody(expr.body, methodEnv.compound.getDeclaredType());
rt = typeCheckFunExprBody(expr.body, methodEnv.compound.getDeclaredType());
}
Implicit(expr) => {
var expected = if(FuncType.?(outer), Function.getReturnType(outer));
rt = inferFuncExprBodyType(expr, expected);
rt = inferFunExprBodyType(expr, expected);
}
Explicit(tref) => {
rt = typeCheckFuncExprBody(expr.body, methodEnv.resolveType(tref));
rt = typeCheckFunExprBody(expr.body, methodEnv.resolveType(tref));
}
}
return expr.exactType = Function.newType(Tuple.newType(Lists.reverse(pl)), rt);
}
def inferFuncExprBodyType(expr: Expr, expected: Type) -> Type { // TODO
def inferFunExprBodyType(expr: Expr, expected: Type) -> Type { // TODO
return if(expected == null, getErrorType(), expected);
}
def typeCheckFuncExprBody(stmt: Stmt, expected: Type) -> Type { // TODO
def typeCheckFunExprBody(stmt: Stmt, expected: Type) -> Type { // TODO
return expected;
}
def typeCheckExpr(expr: Expr, outerType: Type, op: string) {
Expand Down
6 changes: 3 additions & 3 deletions aeneas/src/vst/Vst.v3
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ class VstVisitor<E, R> {
def visitAssign(expr: AssignExpr, env: E) -> R;
def visitBinOp(expr: BinOpExpr, env: E) -> R;
def visitIfExpr(expr: IfExpr, env: E) -> R;
def visitFuncExpr(expr: FuncExpr, env: E) -> R;
def visitFunExpr(expr: FunExpr, env: E) -> R;
}
// The return type of a method or function.
type ReturnType {
Expand Down Expand Up @@ -875,8 +875,8 @@ class IfExpr(start: FilePoint, exprs: VstList<Expr>) extends Expr {
def point() -> FilePoint { return exprs.range(); }
}
// def name(args) { ... }
class FuncExpr(start: FilePoint, name: Token, params: VstList<ParamDecl>, rettype: ReturnType, body: Stmt) extends Expr {
def accept<E, R>(v: VstVisitor<E, R>, env: E) -> R { return v.visitFuncExpr(this, env); }
class FunExpr(start: FilePoint, name: Token, params: VstList<ParamDecl>, rettype: ReturnType, body: Stmt) extends Expr {
def accept<E, R>(v: VstVisitor<E, R>, env: E) -> R { return v.visitFunExpr(this, env); }
def range() -> FileRange { return FileRanges.add(start, body.range()); }
def point() -> FilePoint { return start.rangeOf(1); }
}
Expand Down
4 changes: 2 additions & 2 deletions aeneas/src/vst/VstPrinter.v3
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,8 @@ class VstPrinter extends VstVisitor<int, void> {
def visitIfExpr(expr: IfExpr, indent: int) {
param("IfExpr", null, expr.exprs.list, expr.exactType, expr.implicitType, indent);
}
def visitFuncExpr(expr: FuncExpr, indent: int) {
p.enter("FuncExpr ", indent);
def visitFunExpr(expr: FunExpr, indent: int) {
p.enter("FunExpr ", indent);
if (expr.name != null) Terminal.put1("\"%s\" ", expr.name.image);
Terminal.putc('(');
p.printCommaList(expr.params.list, p.printParam);
Expand Down
2 changes: 1 addition & 1 deletion bin/virgil-mode.el
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(defvar virgil-decls
'("class" "component" "def" "enum" "extends" "export" "in" "import" "layout" "new" "packing" "private" "struct" "super" "type" "var" )
'("class" "component" "def" "enum" "extends" "export" "fun" "in" "import" "layout" "new" "packing" "private" "struct" "super" "type" "var" )
"Virgil declaration keywords.")

(defvar virgil-stmts
Expand Down
3 changes: 3 additions & 0 deletions test/core/parser/kw_fun01.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//@parse = ParseError @ 2:8
class fun {
}
2 changes: 2 additions & 0 deletions test/core/parser/kw_fun02.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse = ParseError @ 2:8
var fun;
2 changes: 2 additions & 0 deletions test/core/parser/kw_fun03.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse =ParseError @ 2:8
def fun = 0;
4 changes: 0 additions & 4 deletions test/funcexpr/empty01.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/anon0.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/anon2.v3

This file was deleted.

4 changes: 0 additions & 4 deletions test/funcexpr/parser/def_expr02.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/empty00.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/empty01.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/empty02.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/empty03.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/empty04.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/empty05.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/empty06.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/empty07.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/empty08.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/opt00.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/opt01.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/opt02.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/opt03.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/opt04.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/param00.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/param01.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/ret00.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/parser/ret01.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/seman/empty00.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/seman/empty01.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/seman/empty02.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/seman/infer00.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/seman/infer01.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/seman/infer02.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/seman/param00.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/seman/param01.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/seman/param02.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/seman/param03.v3

This file was deleted.

2 changes: 0 additions & 2 deletions test/funcexpr/seman/param04.v3

This file was deleted.

2 changes: 1 addition & 1 deletion test/funcexpr/empty00.v3 → test/funexpr/empty00.v3
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//@execute = 112
def main() -> int {
return (def () => 112)();
return (fun () => 112)();
}
4 changes: 4 additions & 0 deletions test/funexpr/empty01.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//@execute = 112
def main() -> int {
return (fun () -> int { return 112; })();
}
2 changes: 1 addition & 1 deletion test/funcexpr/empty02.v3 → test/funexpr/empty02.v3
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//@execute = 112
def main() -> int {
var x = def () -> int { return 112; };
var x = fun () -> int { return 112; };
return x();
}
2 changes: 2 additions & 0 deletions test/funexpr/parser/anon0.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var m = fun () => 0;
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
//@parse = ParseError @ 2:19
var m = def () => { };
var m = fun () => { };
2 changes: 2 additions & 0 deletions test/funexpr/parser/anon2.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var m = fun () -> () { };
2 changes: 2 additions & 0 deletions test/funexpr/parser/anon3.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse = ParseError @ 2:11
var m = def () -> () { };
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//@parse
def foo() {
def m = def () => 0;
def m = fun () => 0;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//@parse
def foo() {
def m = def() => 0;
def m = fun() => 0;
}
4 changes: 4 additions & 0 deletions test/funexpr/parser/def_expr02.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//@parse
def foo() {
def m = fun(x: int) => 0;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//@parse
def foo() {
def m = def(x) => 0;
def m = fun(x) => 0;
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 2 additions & 0 deletions test/funexpr/parser/empty00.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var m = fun n() { };
2 changes: 2 additions & 0 deletions test/funexpr/parser/empty01.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var m = [fun n() { }];
2 changes: 2 additions & 0 deletions test/funexpr/parser/empty02.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var m = (0, fun n() { });
2 changes: 2 additions & 0 deletions test/funexpr/parser/empty03.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var m = (0, fun n() => ());
2 changes: 2 additions & 0 deletions test/funexpr/parser/empty04.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var m = [fun n() => ()];
2 changes: 2 additions & 0 deletions test/funexpr/parser/empty05.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var m = [fun n() => e];
2 changes: 2 additions & 0 deletions test/funexpr/parser/empty06.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var m = fun n() => e;
2 changes: 2 additions & 0 deletions test/funexpr/parser/empty07.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var m = foo(fun n() { });
2 changes: 2 additions & 0 deletions test/funexpr/parser/empty08.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var m = foo(fun n() => 0);
2 changes: 2 additions & 0 deletions test/funexpr/parser/opt00.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var x: int -> void = fun (y) => ();
2 changes: 2 additions & 0 deletions test/funexpr/parser/opt01.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var x: int -> void = fun (y, z: int) => ();
2 changes: 2 additions & 0 deletions test/funexpr/parser/opt02.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var x = fun (y, z: int) => ();
2 changes: 2 additions & 0 deletions test/funexpr/parser/opt03.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var x = fun (y, z: int, w) => ();
2 changes: 2 additions & 0 deletions test/funexpr/parser/opt04.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var x = fun (y, z: int, w) { };
2 changes: 2 additions & 0 deletions test/funexpr/parser/param00.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var m = fun m(x: int) { };
2 changes: 2 additions & 0 deletions test/funexpr/parser/param01.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var m = fun m(x: int, y: T) { };
2 changes: 2 additions & 0 deletions test/funexpr/parser/ret00.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var m = fun m() -> void { };
2 changes: 2 additions & 0 deletions test/funexpr/parser/ret01.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@parse
var m = fun m() -> (int, int) { };
2 changes: 2 additions & 0 deletions test/funexpr/seman/empty00.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@seman
var x: () -> () = fun m() { };
2 changes: 2 additions & 0 deletions test/funexpr/seman/empty01.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@seman = TypeError @ 2:10
var x: int -> () = fun m() { };
2 changes: 2 additions & 0 deletions test/funexpr/seman/empty02.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@seman = TypeError @ 2:10
var x: () -> int = fun m() { };
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 2 additions & 0 deletions test/funexpr/seman/infer00.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@seman
var x: int -> int = fun (y) => y;
2 changes: 2 additions & 0 deletions test/funexpr/seman/infer01.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@seman
var x: float -> int = fun (y) => 0;
2 changes: 2 additions & 0 deletions test/funexpr/seman/infer02.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@seman
var x: float -> int = fun (y) => int.!(y);
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit e77f1f4

Please sign in to comment.