diff --git a/design/Syntax.md b/design/Syntax.md index a57881dc655..2da2ba3e4db 100644 --- a/design/Syntax.md +++ b/design/Syntax.md @@ -7,10 +7,10 @@ Productions marked * probably deferred to later versions. ``` ::= type expressions ? constructor - actor? { ;* } object + (shared|actor)? { ;* } object [ var? ] array ? option - ? ? -> function + (shared|class)? ? -> function async future like structural expansion ( (( :)? ),* ) tuple @@ -43,10 +43,6 @@ Productions marked * probably deferred to later versions. ## Expressions ``` - ::= - new - actor - ::= variable literal @@ -55,7 +51,6 @@ Productions marked * probably deferred to later versions. ( ,* ) tuple . tuple projection ? option injection - ? { ;* } object . object projection := assignment = unary update @@ -113,12 +108,13 @@ Productions marked * probably deferred to later versions. ## Declarations ``` ::= declaration - expression - let = immutable - var (: )? = mutable - func ? ? (: )? = function - type ? = type - actor? class ? (: )? = class + expression + let = immutable + var (: )? = mutable + (new|object|actor|shared) ? =? { ;* } object + shared? func ? ? (: )? =? function + type ? = type + actor? class ? (: )? =? class ``` ## Programs diff --git a/src/lexer.mll b/src/lexer.mll index 48f7e6f221d..b78e7aff851 100644 --- a/src/lexer.mll +++ b/src/lexer.mll @@ -195,6 +195,7 @@ rule token mode = parse | "new" { NEW } | "not" { NOT } | "null" { NULL } + | "object" { OBJECT } | "or" { OR } | "let" { LET } | "loop" { LOOP } diff --git a/src/parser.mly b/src/parser.mly index 80859f2206f..a8333e87232 100644 --- a/src/parser.mly +++ b/src/parser.mly @@ -64,7 +64,7 @@ let share_typfield tf = let share_dec d = match d.it with | FuncD ({it = Type.Local; _} as s, x, tbs, p, t, e) -> - FuncD ({s with it = Type.Sharable}, x, tbs, p, t, e) @? d.at + FuncD ({s with it = Type.Sharable}, x, tbs, p, t, e) @? d.at | _ -> d let share_exp e = @@ -89,7 +89,7 @@ let share_expfield (ef : exp_field) = %token AWAIT ASYNC BREAK CASE CONTINUE LABEL %token IF IN IS ELSE SWITCH LOOP WHILE FOR LIKE RETURN %token ARROW ASSIGN -%token FUNC TYPE ACTOR CLASS PRIVATE NEW SHARED +%token FUNC TYPE OBJECT ACTOR CLASS PRIVATE NEW SHARED %token SEMICOLON SEMICOLON_EOL COMMA COLON SUB DOT QUEST %token AND OR NOT %token ASSERT @@ -167,6 +167,7 @@ seplist1(X, SEP) : %inline obj_sort : | NEW { Type.Object Type.Local @@ at $sloc } + | OBJECT { Type.Object Type.Local @@ at $sloc } | SHARED { Type.Object Type.Sharable @@ at $sloc } | ACTOR { Type.Actor @@ at $sloc } @@ -322,10 +323,6 @@ exp_block : | LCURLY ds=seplist(dec, semicolon) RCURLY { BlockE(ds) @? at $sloc } -exp_obj : - | LCURLY efs=seplist(exp_field, semicolon) RCURLY - { efs } - exp_nullary : | e=exp_block { e } @@ -337,13 +334,6 @@ exp_nullary : { e } | LPAR es=seplist1(exp, COMMA) RPAR { TupE(es) @? at $sloc } - | s=obj_sort xf=id_opt efs=exp_obj - { let anon = if s.it = Type.Actor then "actor" else "object" in - let efs' = - if s.it = Type.Object Type.Local - then efs - else List.map share_expfield efs - in ObjE(s, xf anon $sloc, efs') @? at $sloc } | PRIM s=TEXT { PrimE(s) @? at $sloc } @@ -445,6 +435,14 @@ exp_nonvar : { e } | d=dec_nonvar { DecE(d) @? at $sloc } + (* TODO(andreas): hack, remove *) + | s=obj_sort xf=id_opt EQ? efs=obj_body + { let anon = if s.it = Type.Actor then "actor" else "object" in + let efs' = + if s.it = Type.Object Type.Local + then efs + else List.map share_expfield efs + in ObjE(s, xf anon $sloc, efs') @? at $sloc } exp : | e=exp_nonvar @@ -545,7 +543,7 @@ dec_nonvar : then efs else List.map share_expfield efs in - let id as tid = xf "class" $sloc in + let tid = xf "class" $sloc in ClassD(xf "class" $sloc, tid, tps, s, p, x, efs') @? at $sloc } dec : @@ -555,6 +553,16 @@ dec : { d } | e=exp_nondec { ExpD e @? at $sloc } + (* TODO(andreas): move to dec_nonvar once other production is gone *) + | s=obj_sort xf=id_opt EQ? efs=obj_body + { let anon = if s.it = Type.Actor then "actor" else "object" in + let efs' = + if s.it = Type.Object Type.Local + then efs + else List.map share_expfield efs + in + let p = VarP(xf anon $sloc) @? at $sloc in + LetD(p, ObjE(s, xf anon $sloc, efs') @? at $sloc) @? at $sloc } func_dec : | tps=typ_params_opt p=pat_nullary rt=return_typ? fb=func_body @@ -574,9 +582,13 @@ func_body : | EQ e=exp { (false, e) } | e=exp_block { (true, e) } +obj_body : + | LCURLY efs=seplist(exp_field, semicolon) RCURLY + { efs } + class_body : - | EQ xf=id_opt efs=exp_obj { xf "object" $sloc, efs } - | efs=exp_obj { ("anon-object-" ^ string_of_pos (at $sloc).left) @@ at $sloc, efs } + | EQ xf=id_opt efs=obj_body { xf "object" $sloc, efs } + | efs=obj_body { ("anon-object-" ^ string_of_pos (at $sloc).left) @@ at $sloc, efs } (* Programs *) diff --git a/src/typing.ml b/src/typing.ml index 02cead3b873..95ce10896e2 100644 --- a/src/typing.ml +++ b/src/typing.ml @@ -1033,7 +1033,7 @@ and check_dec env t dec = check_exp env t exp; dec.note <- exp.note; (* TBR: push in external type annotation; - unfortunately, this is enough, because of the earlier recursive phases + unfortunately, this isn't enough, because of the earlier recursive phases | FuncD (id, [], pat, typ, exp) -> (* TBR: special-case unit? *) if T.eq env.cons t T.unit then diff --git a/test/run/actors.as b/test/run/actors.as index d1b8f5bc56c..d1690702064 100644 --- a/test/run/actors.as +++ b/test/run/actors.as @@ -1,6 +1,6 @@ -let tictac_actor = actor self { - tic_msg(n : Int) { if (n > 0) self.tac_msg(n - 1) }; - tac_msg(n : Int) { if (n > 0) self.tic_msg(n - 1) }; +actor tictac_actor { + tic_msg(n : Int) { if (n > 0) tictac_actor.tac_msg(n - 1) }; + tac_msg(n : Int) { if (n > 0) tictac_actor.tic_msg(n - 1) }; }; let _ = tictac_actor.tic_msg(10); @@ -12,9 +12,9 @@ let tictac_async = new this { }; let _ = tictac_async.tic_async(10); -let tictac_actor_async = actor self { - tic_msg_async(n : Int) : async () { if (n > 0) ignore(self.tac_msg_async(n - 1)) }; - tac_msg_async(n : Int) : async () { if (n > 0) ignore(self.tic_msg_async(n - 1)) }; +actor tictac_actor_async { + tic_msg_async(n : Int) : async () { if (n > 0) ignore(tictac_actor_async.tac_msg_async(n - 1)) }; + tac_msg_async(n : Int) : async () { if (n > 0) ignore(tictac_actor_async.tic_msg_async(n - 1)) }; }; let _ = tictac_actor_async.tic_msg_async(10); diff --git a/test/run/is.as b/test/run/is.as index 21a23ebf153..e40755bbca4 100644 --- a/test/run/is.as +++ b/test/run/is.as @@ -22,10 +22,10 @@ assert(not ({} is C)); assert(not ({} is G)); assert(not ({} is A)); assert(not ({} is H)); -assert(not (actor {} is C)); -assert(not (actor {} is G)); -assert(not (actor {} is A)); -assert(not (actor {} is H)); +assert(not ((actor {}) is C)); +assert(not ((actor {}) is G)); +assert(not ((actor {}) is A)); +assert(not ((actor {}) is H)); assert(not (C() is A)); assert(not (C() is G)); diff --git a/test/run/ok/actor.tc.ok b/test/run/ok/actor.tc.ok index c23a254bf29..3be792aed84 100644 --- a/test/run/ok/actor.tc.ok +++ b/test/run/ok/actor.tc.ok @@ -1 +1 @@ -actor.as:14.31-14.49: type error, misplaced await +actor.as:17.17-17.35: type error, misplaced await diff --git a/test/run/switch.as b/test/run/switch.as index 129861b57ab..bb8f404d170 100644 --- a/test/run/switch.as +++ b/test/run/switch.as @@ -26,13 +26,13 @@ let x4 = switch (null : {}?) { }; assert (x4 == 1); -let x5 = switch (new {}?) { +let x5 = switch ((new {})?) { case null 0; case x 1; }; assert (x5 == 1); -let oo : {}? = new {}?; +let oo : {}? = (new {})?; let x6 = switch oo { case null 0; case _ 1;