diff --git a/samples/bank.as b/samples/bank.as index 9d475d2568f..ace922cc10e 100644 --- a/samples/bank.as +++ b/samples/bank.as @@ -13,7 +13,7 @@ actor class Issuer() { }; }; -actor class Account(initialBalance : Int) { +actor class Account(initialBalance : Int) = this { private var balance : Int = initialBalance; getBalance() : async Int { @@ -25,15 +25,15 @@ actor class Account(initialBalance : Int) { return Account(amount); }; - join(account : Account) { // this implicitly asserts that account is Account + join(account : like Account) { + assert(account is Account); let amount = balance; balance := 0; - account.credit(amount); + account.credit(amount, Account); }; - private credit(amount : Int) { - // private implicitly asserts that caller is own class - // by implicitly passing the modref as an extra argument + credit(amount : Int, caller : Class) { + assert(this is caller); balance += amount; }; diff --git a/samples/bank.txt b/samples/bank.txt index 5d6976f5394..c943e400f99 100644 --- a/samples/bank.txt +++ b/samples/bank.txt @@ -1,5 +1,5 @@ -- Checking bank.as: -type Account <: actor {getBalance : shared () -> async Int; isCompatible : shared (like Account) -> async Bool; join : shared Account -> (); split : shared Int -> async Account} +type Account <: actor {credit : shared (Int, Class) -> (); getBalance : shared () -> async Int; isCompatible : shared (like Account) -> async Bool; join : shared (like Account) -> (); split : shared Int -> async Account} type Bank <: actor {getIssuer : shared () -> async Issuer; getReserve : shared () -> async Account} type Issuer <: actor {hasIssued : shared (like Account) -> async Bool} let Account : class Int -> Account @@ -15,8 +15,8 @@ Bank(100) Issuer() <= {hasIssued = func} Account(100) - <= {balance = 100; credit = func; getBalance = func; isCompatible = func; join = func; split = func} - <= {getIssuer = func; getReserve = func; issuer = {hasIssued = func}; reserve = {balance = 100; credit = func; getBalance = func; isCompatible = func; join = func; split = func}} + <= {credit = func; getBalance = func; isCompatible = func; join = func; split = func} + <= {getIssuer = func; getReserve = func} test() -> async bank.as:56.40-68.2 <= async _ @@ -28,8 +28,8 @@ test() -> async bank.as:7.32-7.51 <= async _ <- async bank.as:7.32-7.51 - <= {balance = 100; credit = func; getBalance = func; isCompatible = func; join = func; split = func} -<- await bank.as:57.17-57.40({balance = 100; credit = func; getBalance = func; isCompatible = func; join = func; split = func}) + <= {credit = func; getBalance = func; isCompatible = func; join = func; split = func} +<- await bank.as:57.17-57.40({credit = func; getBalance = func; isCompatible = func; join = func; split = func}) -> message split(10) => await bank.as:58.12-58.35 <- message split(10) @@ -38,9 +38,9 @@ test() <= async _ <- async bank.as:23.39-26.4 Account(10) - <= {balance = 10; credit = func; getBalance = func; isCompatible = func; join = func; split = func} - <= {balance = 10; credit = func; getBalance = func; isCompatible = func; join = func; split = func} -<- await bank.as:58.12-58.35({balance = 10; credit = func; getBalance = func; isCompatible = func; join = func; split = func}) + <= {credit = func; getBalance = func; isCompatible = func; join = func; split = func} + <= {credit = func; getBalance = func; isCompatible = func; join = func; split = func} +<- await bank.as:58.12-58.35({credit = func; getBalance = func; isCompatible = func; join = func; split = func}) -> message split(10) => await bank.as:59.12-59.35 <- message split(10) @@ -49,16 +49,16 @@ test() <= async _ <- async bank.as:23.39-26.4 Account(10) - <= {balance = 10; credit = func; getBalance = func; isCompatible = func; join = func; split = func} - <= {balance = 10; credit = func; getBalance = func; isCompatible = func; join = func; split = func} -<- await bank.as:59.12-59.35({balance = 10; credit = func; getBalance = func; isCompatible = func; join = func; split = func}) - show("reserve", {balance = 80; credit = func; getBalance = func; isCompatible = func; join = func; split = func}) + <= {credit = func; getBalance = func; isCompatible = func; join = func; split = func} + <= {credit = func; getBalance = func; isCompatible = func; join = func; split = func} +<- await bank.as:59.12-59.35({credit = func; getBalance = func; isCompatible = func; join = func; split = func}) + show("reserve", {credit = func; getBalance = func; isCompatible = func; join = func; split = func}) <= () - show("a1", {balance = 10; credit = func; getBalance = func; isCompatible = func; join = func; split = func}) + show("a1", {credit = func; getBalance = func; isCompatible = func; join = func; split = func}) <= () - show("a2", {balance = 10; credit = func; getBalance = func; isCompatible = func; join = func; split = func}) + show("a2", {credit = func; getBalance = func; isCompatible = func; join = func; split = func}) <= () - transfer({balance = 10; credit = func; getBalance = func; isCompatible = func; join = func; split = func}, {balance = 10; credit = func; getBalance = func; isCompatible = func; join = func; split = func}, 5) + transfer({credit = func; getBalance = func; isCompatible = func; join = func; split = func}, {credit = func; getBalance = func; isCompatible = func; join = func; split = func}, 5) -> async bank.as:46.79-49.2 <= async _ => await bank.as:63.3-63.28 @@ -71,30 +71,32 @@ test() <= async _ <- async bank.as:23.39-26.4 Account(5) - <= {balance = 5; credit = func; getBalance = func; isCompatible = func; join = func; split = func} - <= {balance = 5; credit = func; getBalance = func; isCompatible = func; join = func; split = func} -<- await bank.as:47.13-47.39({balance = 5; credit = func; getBalance = func; isCompatible = func; join = func; split = func}) - -> message join({balance = 10; credit = func; getBalance = func; isCompatible = func; join = func; split = func}) + <= {credit = func; getBalance = func; isCompatible = func; join = func; split = func} + <= {credit = func; getBalance = func; isCompatible = func; join = func; split = func} +<- await bank.as:47.13-47.39({credit = func; getBalance = func; isCompatible = func; join = func; split = func}) + -> message join({credit = func; getBalance = func; isCompatible = func; join = func; split = func}) <= () -<- message join({balance = 10; credit = func; getBalance = func; isCompatible = func; join = func; split = func}) - join({balance = 10; credit = func; getBalance = func; isCompatible = func; join = func; split = func}) - credit(5) - <= () +<- message join({credit = func; getBalance = func; isCompatible = func; join = func; split = func}) + join({credit = func; getBalance = func; isCompatible = func; join = func; split = func}) + -> message credit(5, class) + <= () +<- message credit(5, class) + credit(5, class) <= () <- await bank.as:63.3-63.28() - show("reserve", {balance = 80; credit = func; getBalance = func; isCompatible = func; join = func; split = func}) + show("reserve", {credit = func; getBalance = func; isCompatible = func; join = func; split = func}) <= () - show("a1", {balance = 5; credit = func; getBalance = func; isCompatible = func; join = func; split = func}) + show("a1", {credit = func; getBalance = func; isCompatible = func; join = func; split = func}) <= () - show("a2", {balance = 15; credit = func; getBalance = func; isCompatible = func; join = func; split = func}) + show("a2", {credit = func; getBalance = func; isCompatible = func; join = func; split = func}) <= () - <= ({balance = 5; credit = func; getBalance = func; isCompatible = func; join = func; split = func}, {balance = 15; credit = func; getBalance = func; isCompatible = func; join = func; split = func}) + <= ({credit = func; getBalance = func; isCompatible = func; join = func; split = func}, {credit = func; getBalance = func; isCompatible = func; join = func; split = func}) -- Finished bank.as: let Account : class Int -> Account = class let Bank : class Int -> Bank = class let Issuer : class () -> Issuer = class -let bank : Bank = {getIssuer = func; getReserve = func; issuer = {hasIssued = func}; reserve = {balance = 80; credit = func; getBalance = func; isCompatible = func; join = func; split = func}} -let main : async (Account, Account) = async ({balance = 5; credit = func; getBalance = func; isCompatible = func; join = func; split = func}, {balance = 15; credit = func; getBalance = func; isCompatible = func; join = func; split = func}) +let bank : Bank = {getIssuer = func; getReserve = func} +let main : async (Account, Account) = async ({credit = func; getBalance = func; isCompatible = func; join = func; split = func}, {credit = func; getBalance = func; isCompatible = func; join = func; split = func}) let show : (Text, Account) -> () = func let test : () -> async (Account, Account) = func let transfer : (Account, Account, Int) -> async () = func diff --git a/samples/cheque.txt b/samples/cheque.txt index 87950094b9e..c0ebd18060c 100644 --- a/samples/cheque.txt +++ b/samples/cheque.txt @@ -18,8 +18,8 @@ Bank(100) Issuer() <= {hasIssued = func} Account(100) - <= {balance = 100; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func} - <= {getIssuer = func; getReserve = func; issuer = {hasIssued = func}; reserve = {balance = 100; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}} + <= {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func} + <= {getIssuer = func; getReserve = func} test() -> async cheque.as:76.39-88.2 <= async _ @@ -31,8 +31,8 @@ test() -> async cheque.as:7.32-7.51 <= async _ <- async cheque.as:7.32-7.51 - <= {balance = 100; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func} -<- await cheque.as:77.17-77.40({balance = 100; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) + <= {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func} +<- await cheque.as:77.17-77.40({credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) -> message split(10) => await cheque.as:78.12-78.35 <- message split(10) @@ -41,9 +41,9 @@ test() <= async _ <- async cheque.as:32.39-35.4 Account(10) - <= {balance = 10; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func} - <= {balance = 10; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func} -<- await cheque.as:78.12-78.35({balance = 10; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) + <= {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func} + <= {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func} +<- await cheque.as:78.12-78.35({credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) -> message split(10) => await cheque.as:79.12-79.35 <- message split(10) @@ -52,35 +52,35 @@ test() <= async _ <- async cheque.as:32.39-35.4 Account(10) - <= {balance = 10; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func} - <= {balance = 10; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func} -<- await cheque.as:79.12-79.35({balance = 10; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) - show("reserve", {balance = 80; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) + <= {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func} + <= {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func} +<- await cheque.as:79.12-79.35({credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) + show("reserve", {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) <= () - show("a1", {balance = 10; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) + show("a1", {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) <= () - show("a2", {balance = 10; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) + show("a2", {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) <= () - transfer({balance = 10; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}, {balance = 10; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}, 5) + transfer({credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}, {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}, 5) -> async cheque.as:64.79-67.2 <= async _ => await cheque.as:83.3-83.28 <- async cheque.as:64.79-67.2 - -> message invoice(5, {balance = 10; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) + -> message invoice(5, {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) => await cheque.as:65.16-65.53 -<- message invoice(5, {balance = 10; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) - invoice(5, {balance = 10; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) +<- message invoice(5, {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) + invoice(5, {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) -> async cheque.as:41.59-44.4 <= async _ <- async cheque.as:41.59-44.4 - Cheque(5, {balance = 10; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) - <= {current = 5; deposit = func} - <= {current = 5; deposit = func} -<- await cheque.as:65.16-65.53({current = 5; deposit = func}) - -> message deposit({current = 5; deposit = func}) + Cheque(5, {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) + <= {deposit = func} + <= {deposit = func} +<- await cheque.as:65.16-65.53({deposit = func}) + -> message deposit({deposit = func}) <= () -<- message deposit({current = 5; deposit = func}) - deposit({current = 5; deposit = func}) +<- message deposit({deposit = func}) + deposit({deposit = func}) -> message deposit() <= () <- message deposit() @@ -91,7 +91,7 @@ test() credit(5) <= () <- await cheque.as:83.3-83.28() - show("reserve", {balance = 80; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) + show("reserve", {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) <= () -> message getBalance() => await cheque.as:85.21-85.42 @@ -115,14 +115,14 @@ test() <- await cheque.as:86.21-86.42(15) showBalance("b2", 15) <= () - <= ({balance = 5; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}, {balance = 15; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) + <= ({credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}, {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) -- Finished cheque.as: let Account : class Int -> Account = class let Bank : class Int -> Bank = class let Cheque : class (Int, Account) -> Cheque = class let Issuer : class () -> Issuer = class -let bank : Bank = {getIssuer = func; getReserve = func; issuer = {hasIssued = func}; reserve = {balance = 80; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}} -let main : async (Account, Account) = async ({balance = 5; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}, {balance = 15; credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) +let bank : Bank = {getIssuer = func; getReserve = func} +let main : async (Account, Account) = async ({credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}, {credit = func; deposit = func; getBalance = func; invoice = func; isCompatible = func; join = func; split = func}) let show : (Text, Account) -> () = func let showBalance : (Text, Int) -> () = func let test : () -> async (Account, Account) = func diff --git a/samples/counter.txt b/samples/counter.txt index 47cdd4a8a8c..4df26ec213a 100644 --- a/samples/counter.txt +++ b/samples/counter.txt @@ -8,7 +8,7 @@ let testDec : () -> () let testRead : () -> () -- Interpreting counter.as: Counter(10) - <= {c = 10; dec = func; read = func} + <= {dec = func; read = func} testDec() -> message dec() -> message dec() @@ -288,7 +288,7 @@ testRead() <= () -- Finished counter.as: let Counter : class Int -> Counter = class -let c : Counter = {c = -10; dec = func; read = func} +let c : Counter = {dec = func; read = func} let show : (Text, Int) -> () = func let showAsync : (Text, async Int) -> () = func let testDec : () -> () = func diff --git a/samples/quicksort.txt b/samples/quicksort.txt index c7520c795ce..e82cb16c9f9 100644 --- a/samples/quicksort.txt +++ b/samples/quicksort.txt @@ -7,7 +7,7 @@ let cmpi : (Int, Int) -> Int let qs : QS -- Interpreting quicksort.as: QS(func) - <= {partition = func; quicksort = func; swap = func; trace = func} + <= {quicksort = func} quicksort([8, 3, 9, 5, 2], 0, 4) partition([8, 3, 9, 5, 2], 0, 4) trace([8, 3, 9, 5, 2]) @@ -100,5 +100,5 @@ quicksort([8, 3, 9, 5, 2], 0, 4) let QS : class ((T, T) -> Int) -> QS = class let a : Array = [2, 3, 5, 8, 9] let cmpi : (Int, Int) -> Int = func -let qs : QS = {partition = func; quicksort = func; swap = func; trace = func} +let qs : QS = {quicksort = func} diff --git a/src/arrange.ml b/src/arrange.ml index 75be6bcfcf5..ce8cce742c0 100644 --- a/src/arrange.ml +++ b/src/arrange.ml @@ -160,7 +160,7 @@ and dec d = match d.it with "FuncD" $$ [Atom (sharing s.it); id i] @ List.map typ_bind tp @ [pat p; typ t; exp e] | TypD (i, tp, t) -> "TypD" $$ [id i] @ List.map typ_bind tp @ [typ t] - | ClassD (i, j, tp, s, p, efs) -> - "ClassD" $$ id i :: id j :: List.map typ_bind tp @ [obj_sort s; pat p] @ List.map exp_field efs + | ClassD (i, j, tp, s, p, i', efs) -> + "ClassD" $$ id i :: id j :: List.map typ_bind tp @ [obj_sort s; pat p; id i'] @ List.map exp_field efs and prog prog = "BlockE" $$ List.map dec prog.it diff --git a/src/async.ml b/src/async.ml index ffcbc34d981..1e7f16ede91 100644 --- a/src/async.ml +++ b/src/async.ml @@ -406,9 +406,9 @@ and t_dec' dec' = | _ -> failwith "async.ml t_dec': funcD3" end end - | ClassD (id, lab, typbinds, sort, pat, fields) -> + | ClassD (id, lab, typbinds, sort, pat, id', fields) -> let fields' = t_fields fields in - ClassD (id, lab, t_typbinds typbinds, sort, t_pat pat, fields') + ClassD (id, lab, t_typbinds typbinds, sort, t_pat pat, id', fields') and t_decs decs = List.map t_dec decs diff --git a/src/await.ml b/src/await.ml index 747993e3927..2430d5aa71d 100644 --- a/src/await.ml +++ b/src/await.ml @@ -113,7 +113,7 @@ and infer_effect_dec dec = T.Triv | FuncD (s, v, tps, p, t, e) -> T.Triv - | ClassD (v, l, tps, s, p, efs) -> + | ClassD (v, l, tps, s, p, v', efs) -> T.Triv (* sugar *) @@ -436,10 +436,10 @@ and t_dec' context dec' = let context' = LabelEnv.add id_ret Label LabelEnv.empty in FuncD (sh, id, typbinds, pat, typ,t_exp context' exp) - | ClassD (id, lab, typbinds, sort, pat, fields) -> + | ClassD (id, lab, typbinds, sort, pat, id', fields) -> let context' = LabelEnv.add id_ret Label LabelEnv.empty in let fields' = t_fields context' fields in - ClassD (id, lab, typbinds, sort, pat, fields') + ClassD (id, lab, typbinds, sort, pat, id', fields') and t_decs context decs = List.map (t_dec context) decs and t_fields context fields = List.map (fun (field:exp_field) -> @@ -831,7 +831,7 @@ and c_dec context dec = (k -@- define_idE id Var v))) end | FuncD (_, id, _ (* typbinds *), _ (* pat *), _ (* typ *), _ (* exp *) ) - | ClassD (id, _ (* lab *), _ (* typbinds *), _ (* sort *), _ (* pat *), _ (* fields *) ) -> + | ClassD (id, _ (* lab *), _ (* typbinds *), _ (* sort *), _ (* pat *), _ (* id *), _ (* fields *) ) -> (* todo: use a block not lets as in LetD *) let func_typ = typ_dec dec in let k = fresh_cont func_typ in @@ -868,7 +868,7 @@ and declare_dec dec exp : exp = | LetD (pat, _) -> declare_pat pat exp | VarD (id, exp1) -> declare_id id (T.Mut (typ exp1)) exp | FuncD (_, id, _, _, _, _) - | ClassD (id, _, _, _, _, _) -> declare_id id (typ_dec dec) exp + | ClassD (id, _, _, _, _, _, _) -> declare_id id (typ_dec dec) exp and declare_decs decs exp : exp = match decs with diff --git a/src/awaitopt.ml b/src/awaitopt.ml index e5b6d80821e..a63e97d6f99 100644 --- a/src/awaitopt.ml +++ b/src/awaitopt.ml @@ -114,7 +114,7 @@ and infer_effect_dec dec = T.Triv | FuncD (s, v, tps, p, t, e) -> T.Triv - | ClassD (v, l, tps, s, p, efs) -> + | ClassD (v, l, tps, s, p, v', efs) -> T.Triv @@ -497,10 +497,10 @@ and t_dec' context dec' = | FuncD (s, id, typbinds, pat, typ, exp) -> let context' = LabelEnv.add id_ret Label LabelEnv.empty in FuncD (s, id, typbinds, pat, typ,t_exp context' exp) - | ClassD (id, lab, typbinds, sort, pat, fields) -> + | ClassD (id, lab, typbinds, sort, pat, id', fields) -> let context' = LabelEnv.add id_ret Label LabelEnv.empty in let fields' = t_fields context' fields in - ClassD (id, lab, typbinds, sort, pat, fields') + ClassD (id, lab, typbinds, sort, pat, id', fields') and t_decs context decs = List.map (t_dec context) decs @@ -880,7 +880,7 @@ and c_dec context dec (k:kont) = (fun v -> k -@- define_idE id Var v)) end | FuncD (_, id, _ (* typbinds *), _ (* pat *), _ (* typ *), _ (* exp *) ) - | ClassD (id, _ (* name *), _ (* typbinds *), _ (* sort *), _ (* pat *), _ (* fields *) ) -> + | ClassD (id, _ (* name *), _ (* typbinds *), _ (* sort *), _ (* pat *), _ (* id *), _ (* fields *) ) -> let func_typ = typ dec in let v = fresh_id func_typ in let u = fresh_id T.unit in @@ -906,7 +906,7 @@ and declare_dec dec exp : exp = | LetD (pat, _) -> declare_pat pat exp | VarD (id, exp1) -> declare_id id (T.Mut (typ exp1)) exp | FuncD (_, id, _, _, _, _) - | ClassD (id, _, _, _, _, _) -> declare_id id (typ dec) exp + | ClassD (id, _, _, _, _, _, _) -> declare_id id (typ dec) exp and declare_decs decs exp : exp = match decs with diff --git a/src/compile.ml b/src/compile.ml index d6fe0f1ddaf..84af0fead74 100644 --- a/src/compile.ml +++ b/src/compile.ml @@ -3194,7 +3194,7 @@ and compile_dec last pre_env dec : E.t * G.t * (E.t -> G.t) = match dec.it with Closure.dec pre_env last name captured mk_pat mk_body dec.at (* Classes are desguared to functions and objects. *) - | ClassD (name, _, typ_params, s, p, efs) -> + | ClassD (name, _, typ_params, s, p, self, efs) -> let captured = Freevars.captured_exp_fields p efs in let mk_pat env1 = compile_mono_pat env1 p in let mk_body env1 compile_fun_identifier = @@ -3206,7 +3206,7 @@ and compile_dec last pre_env dec : E.t * G.t * (E.t -> G.t) = match dec.it with identifier, as provided by Func.dec: For closures it is the pointer to the closure. For functions it is the function id (shifted to never class with pointers) *) - Object.lit env1 None (Some compile_fun_identifier) fs' in + Object.lit env1 (Some self) (Some compile_fun_identifier) fs' in Closure.dec pre_env last name captured mk_pat mk_body dec.at and compile_decs env decs : G.t = snd (compile_decs_block env true decs) diff --git a/src/freevars.ml b/src/freevars.ml index 921323440f4..83911d680ba 100644 --- a/src/freevars.ml +++ b/src/freevars.ml @@ -103,8 +103,8 @@ and dec d = match d.it with | FuncD (s, i, tp, p, t, e) -> (S.empty, S.singleton i.it) +++ (exp e /// pat p) | TypD (i, tp, t) -> (S.empty, S.empty) - | ClassD (i, l, tp, s, p, efs) -> - (S.empty, S.singleton i.it) +++ (close (exp_fields efs) /// pat p) + | ClassD (i, l, tp, s, p, i', efs) -> + (S.empty, S.singleton i.it) +++ (close (exp_fields efs) /// pat p // i'.it) (* The variables captured by a function. May include the function itself! *) and captured p e = S.elements (exp e /// pat p) diff --git a/src/interpret.ml b/src/interpret.ml index 1444ff72119..03ed0a89a61 100644 --- a/src/interpret.ml +++ b/src/interpret.ml @@ -251,11 +251,11 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | ProjE (exp1, n) -> interpret_exp env exp1 (fun v1 -> k (List.nth (V.as_tup v1) n)) | ObjE (sort, id, fields) -> - interpret_obj env sort id fields k + interpret_obj env sort id None fields k | DotE (exp1, {it = Name n;_}) -> interpret_exp env exp1 (fun v1 -> let _, fs = V.as_obj v1 in - k (try find n fs with _ -> (assert false)) + k (try find n fs with _ -> assert false) ) | AssignE (exp1, exp2) -> interpret_exp_mut env exp1 (fun v1 -> @@ -539,28 +539,21 @@ and match_pats pats vs ve : val_env option = (* Objects *) -and interpret_obj env sort id fields (k : V.value V.cont) = - let ve0 = declare_id id in - let private_ve, public_ve = declare_exp_fields fields ve0 V.Env.empty in - let env' = adjoin_vals env private_ve in - interpret_fields env' sort.it None fields public_ve (fun v -> - define_id (adjoin_vals env ve0) id v; +and interpret_obj env sort id co fields (k : V.value V.cont) = + let ve = declare_exp_fields fields (declare_id id) in + let env' = adjoin_vals env ve in + interpret_fields env' sort.it co fields V.Env.empty (fun v -> + define_id env' id v; k v ) -and declare_field (id,name) = - let p = Lib.Promise.make () in - V.Env.singleton id.it p, - V.Env.singleton (string_of_name name.it) p - - -and declare_exp_fields fields private_ve public_ve : val_env * val_env = +and declare_exp_fields fields ve : val_env = match fields with - | [] -> private_ve, public_ve + | [] -> ve | {it = {id; name; mut; priv; _}; _}::fields' -> - let private_ve', public_ve' = declare_field (id,name) in - declare_exp_fields fields' - (V.Env.adjoin private_ve private_ve') (V.Env.adjoin public_ve public_ve') + let p = Lib.Promise.make () in + let ve' = V.Env.singleton id.it p in + declare_exp_fields fields' (V.Env.adjoin ve ve') and interpret_fields env s co fields ve (k : V.value V.cont) = @@ -574,7 +567,11 @@ and interpret_fields env s co fields ve (k : V.value V.cont) = | Var -> V.Mut (ref v) in define_id env id v'; - interpret_fields env s co fields' ve k + let ve' = + if priv.it = Private + then ve + else V.Env.add (string_of_name name.it) (V.Env.find id.it env.vals) ve + in interpret_fields env s co fields' ve' k ) (* Blocks and Declarations *) @@ -592,7 +589,7 @@ and declare_dec dec : val_env = | LetD (pat, _) -> declare_pat pat | VarD (id, _) | FuncD (_, id, _, _, _, _) - | ClassD (id, _, _, _, _, _) -> declare_id id + | ClassD (id, _, _, _, _, _, _) -> declare_id id and declare_decs decs ve : val_env = match decs with @@ -630,16 +627,10 @@ and interpret_dec env dec (k : V.value V.cont) = in define_id env id v; k v - | ClassD (id, _, _typbinds, sort, pat, fields) -> + | ClassD (id, _, _typbinds, sort, pat, id', fields) -> let c = V.new_class () in let f = interpret_func env id pat - (fun env' k' -> - let private_ve, public_ve = - declare_exp_fields fields V.Env.empty V.Env.empty in - interpret_fields (adjoin_vals env' private_ve) sort.it (Some c) - fields public_ve k' - ) - in + (fun env' k' -> interpret_obj env' sort id' (Some c) fields k') in let v = V.Func (Some c, f) in define_id env id v; k v diff --git a/src/parser.mly b/src/parser.mly index 3fe9e6882bb..9f5259c89ba 100644 --- a/src/parser.mly +++ b/src/parser.mly @@ -535,14 +535,15 @@ dec_nonexp : { (fd s (xf "func" $sloc)).it @? at $sloc } | TYPE x=id tps=typ_params_opt EQ t=typ { TypD(x, tps, t) @? at $sloc } - | s=obj_sort_opt CLASS xf=id_opt tps=typ_params_opt p=pat_nullary efs=class_body - { let efs' = + | s=obj_sort_opt CLASS xf=id_opt tps=typ_params_opt p=pat_nullary xefs=class_body + { let x, efs = xefs in + let efs' = if s.it = Type.Object Type.Local then efs else List.map share_expfield efs in let id as tid = xf "class" $sloc in - ClassD(xf "class" $sloc, tid, tps, s, p, efs') @? at $sloc } + ClassD(xf "class" $sloc, tid, tps, s, p, x, efs') @? at $sloc } dec : | d=dec_nonexp { d } @@ -568,8 +569,8 @@ func_body : | e=exp_block { (true, e) } class_body : - | EQ efs=exp_obj { efs } - | efs=exp_obj { efs } + | 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 } (* Programs *) diff --git a/src/rename.ml b/src/rename.ml index 0b28a63c235..dd912ba4686 100644 --- a/src/rename.ml +++ b/src/rename.ml @@ -156,13 +156,13 @@ and dec' rho d = match d with | TypD (i, tp, t) -> (* we don't rename type names *) (fun rho -> d), rho - | ClassD (i, l, tp, s, p, efs) -> - (* TBR - we can't really alpha-convert class constructors - should we internally separate type name from constructor name *) + | ClassD (i, l, tp, s, p, i2, efs) -> let i',rho = id_bind rho i in (fun rho' -> let p',rho'' = pat rho' p in - let efs' = exp_fields rho'' efs in - ClassD(i', l, tp, s, p', efs')), + let i2',rho''' = id_bind rho'' i2 in + let efs' = exp_fields rho''' efs in + ClassD(i', l, tp, s, p', i2', efs')), rho and decs rho ds = diff --git a/src/syntax.ml b/src/syntax.ml index 0e724838578..cb1b6132825 100644 --- a/src/syntax.ml +++ b/src/syntax.ml @@ -14,6 +14,7 @@ type name = name' Source.phrase and name' = Name of string let string_of_name (Name s ) = s + (* Types *) type sharing = Type.sharing Source.phrase @@ -159,7 +160,7 @@ and exp' = | DecE of dec (* declaration *) | DeclareE of id * Type.typ * exp (* local promise (internal) *) | DefineE of id * mut * exp (* promise fulfillment (internal) *) - | NewObjE of obj_sort * (name*id) list (* make an object, preserving mutable identity (internal) *) + | NewObjE of obj_sort * (name * id) list (* make an object, preserving mutable identity (internal) *) (* | ThrowE of exp list (* throw exception *) | TryE of exp * case list (* catch eexception *) @@ -168,7 +169,7 @@ and exp' = *) and exp_field = exp_field' Source.phrase -and exp_field' = {name: name; id : id; exp : exp; mut : mut; priv : priv} +and exp_field' = {name : name; id : id; exp : exp; mut : mut; priv : priv} and case = case' Source.phrase and case' = {pat : pat; exp : exp} @@ -183,7 +184,7 @@ and dec' = | VarD of id * exp (* mutable *) | FuncD of sharing * id * typ_bind list * pat * typ * exp (* function *) | TypD of id * typ_bind list * typ (* type *) - | ClassD of id (* term id*) * id (*type id*) * typ_bind list * obj_sort * pat * exp_field list (* class *) + | ClassD of id (*term id*) * id (*type id*) * typ_bind list * obj_sort * pat * id * exp_field list (* class *) (* Program *) diff --git a/src/type.ml b/src/type.ml index edf1447aa0a..1b68053880b 100644 --- a/src/type.ml +++ b/src/type.ml @@ -362,7 +362,7 @@ let rec avoid' env env' = function List.map (avoid' env env') ts1, List.map (avoid' env env') ts2) | Opt t -> Opt (avoid' env env' t) | Async t -> Async (avoid' env env' t) - | Like t -> Like (avoid' env env' t) + | Like t -> avoid' env env' (promote env t) | Obj (s, fs) -> Obj (s, List.map (avoid_field env env') fs) | Mut t -> Mut (avoid' env env' t) @@ -386,7 +386,7 @@ let rel_list p env rel eq xs1 xs2 = let str = ref (fun _ -> failwith "") let rec rel_typ env rel eq t1 t2 = -(*printf "[sub] %s == %s\n" (string_of_typ t1) (string_of_typ t2); flush_all();*) +(*Printf.printf "[sub] %s == %s\n%!" (!str t1) (!str t2);*) t1 == t2 || S.mem (t1, t2) !rel || begin rel := S.add (t1, t2) !rel; match t1, t2 with @@ -477,10 +477,10 @@ let rec rel_typ env rel eq t1 t2 = rel_typ env rel eq t1' t2' | Async t1', Shared -> rel_typ env rel eq t1' Shared - | Like t1', Like t2' -> - rel_typ env rel eq t1' t2' - | Like t1', Shared -> - rel_typ env rel eq t1' Shared + | Like t1', t2 -> + rel_typ env rel eq (promote env t1') t2 + | t1, Like t2' -> + rel_typ env rel eq t1 (promote env t2') | Mut t1', Mut t2' -> eq_typ env rel eq t1' t2' | _, _ -> false diff --git a/src/typing.ml b/src/typing.ml index 1f3a7b86d96..52034a2e45b 100644 --- a/src/typing.ml +++ b/src/typing.ml @@ -63,12 +63,14 @@ let empty_env = let add_lab c x t = {c with labs = T.Env.add x t c.labs} let add_val c x t = {c with vals = T.Env.add x t c.vals} -(*let add_con c con k = {c with cons = Con.Env.add con k c.cons}*) +(* +let add_con c con k = {c with cons = Con.Env.add con k c.cons} let add_typ c x con k = { c with typs = T.Env.add x con c.typs; cons = Con.Env.add con k c.cons; } +*) let add_typs c xs cs ks = { c with @@ -374,7 +376,7 @@ and infer_exp' env exp : T.typ = (T.string_of_typ_expand env.cons t1) ) | ObjE (sort, id, fields) -> - fst (infer_obj env sort.it id fields) + infer_obj env sort.it id fields | DotE (exp1, {it = Name n;_}) -> let t1 = infer_exp_promote env exp1 in (try @@ -822,33 +824,19 @@ and check_pats env ts pats ve at : val_env = (* Objects *) -and infer_obj env s id fields : T.typ * T.typ = - (* TBR: rethink private *) -(*Printf.printf "[object] gather fields, env:\n"; -print_ce env.cons; -print_ve env.vals;*) +and infer_obj env s id fields : T.typ = let pre_ve = gather_exp_fields id.it fields in -(*Printf.printf "[object] pre-infer fields\n";*) let pre_env = adjoin_vals {env with pre = true} pre_ve in - let tfs, tfs_inner, ve = infer_exp_fields pre_env s id.it T.Pre fields in - let t_inner = T.Obj (s, tfs_inner) in -(*print_ve ve; -Printf.printf "[object] infer fields, env:\n"; -print_ce env.cons; -print_ve (adjoin_vals (add_val env id.it ((*t*) t_inner, T.Const)) ve).vals;*) + let tfs, ve = infer_exp_fields pre_env s id.it T.Pre fields in + let t = T.Obj (s, tfs) in if not env.pre then begin - let env' = adjoin_vals (add_val env id.it (*t*) t_inner) ve in - ignore (infer_exp_fields env' s id.it (*t*) t_inner fields) + let env' = adjoin_vals (add_val env id.it t) ve in + ignore (infer_exp_fields env' s id.it t fields) end; -(*Printf.printf "[object] done\n";*) - T.Obj (s, tfs), t_inner + t and check_obj env s tfs id fields at : T.typ = - (* TBR: rethink private *) -(*Printf.printf "[object] gather fields, env:\n"; -print_ce env.cons; -print_ve env.vals;*) let pre_ve = gather_exp_fields id.it fields in let pre_ve' = List.fold_left (fun ve {T.name; typ = t} -> if not (T.Env.mem name ve) then @@ -858,18 +846,12 @@ print_ve env.vals;*) T.Env.add name t ve ) pre_ve tfs in -(*Printf.printf "[object] pre-infer fields\n";*) let pre_env = adjoin_vals {env with pre = true} pre_ve' in - let _, tfs_inner, ve = infer_exp_fields pre_env s id.it T.Pre fields in - let t_inner = T.Obj (s, tfs_inner) in -(*print_ve ve; -Printf.printf "[object] infer fields, env:\n"; -print_ce env.cons; -print_ve (adjoin_vals (add_val env id.it ((*t*) t_inner, T.Const)) ve).vals;*) - let env' = adjoin_vals (add_val env id.it (*t*) t_inner) ve in - ignore (infer_exp_fields env' s id.it (*t*) t_inner fields); -(*Printf.printf "[object] done\n";*) - t_inner + let tfs, ve = infer_exp_fields pre_env s id.it T.Pre fields in + let t = T.Obj (s, tfs) in + let env' = adjoin_vals (add_val env id.it t) ve in + ignore (infer_exp_fields env' s id.it t fields); + t and gather_exp_fields id fields : val_env = @@ -883,11 +865,11 @@ and gather_exp_field ve field : val_env = T.Env.add id.it T.Pre ve -and infer_exp_fields env s id t fields : T.field list * T.field list * val_env = +and infer_exp_fields env s id t fields : T.field list * val_env = let env' = add_val env id t in - let tfs, tfs_inner, ve = - List.fold_left (infer_exp_field env' s) ([], [], T.Env.empty) fields in - List.sort compare tfs, List.sort compare tfs_inner, ve + let tfs, ve = + List.fold_left (infer_exp_field env' s) ([], T.Env.empty) fields in + List.sort compare tfs, ve and is_func_exp exp = match exp.it with @@ -900,7 +882,7 @@ and is_func_dec dec = | FuncD _ -> true | _ -> Printf.printf "[2]%!"; false -and infer_exp_field env s (tfs, tfs_inner, ve) field : T.field list * T.field list * val_env = +and infer_exp_field env s (tfs, ve) field : T.field list * val_env = let {id; name; exp; mut; priv} = field.it in let t = match T.Env.find id.it env.vals with @@ -920,55 +902,31 @@ and infer_exp_field env s (tfs, tfs_inner, ve) field : T.field list * T.field li (string_of_name name.it) (T.string_of_typ_expand env.cons t) end; let ve' = T.Env.add id.it t ve in - let tfs_inner' = {T.name = string_of_name name.it; typ = t} :: tfs_inner in let tfs' = - if priv.it = Private then tfs else {T.name = string_of_name name.it; typ = t} :: tfs - in tfs', tfs_inner', ve' - - -(* -and check_exp_fields env s tfs id t fields : T.field list * val_env = - let env' = add_val env id t in - let tfs_inner, ve = - List.fold_left (check_exp_field env' s tfs) ([], T.Env.empty) fields in - List.sort compare tfs_inner, ve - -and check_exp_field env s tfs (tfs_inner, ve) field : T.field list * val_env = - let {id; exp; mut; priv} = field.it in - if priv = Private then begin - let _, tfs_inner', ve' = - infer_exp_field env s ([], tfs_inner, ve) field - in tfs_inner', ve' - end else begin - check_exp (adjoin_vals env ve) (T.Env.find env.vals id.it) exp; - if s = T.Actor && priv.it = Public && not (is_async_typ env t) then - error field.at "public actor field %s has non-async type %s" - id.it (T.string_of_typ t) - end; - let ve' = T.Env.add id.it t ve in - let tfs_inner' = {T.name = id.it; typ = t} :: tfs_inner in - tfs_inner', ve' -*) + if priv.it = Private + then tfs + else {T.name = string_of_name name.it; typ = t} :: tfs + in tfs', ve' (* Blocks and Declarations *) and infer_block env decs at : T.typ * scope = - let _, _, ce as scope, ce_inner = infer_block_decs env decs in - let t = infer_block_exps (adjoin env scope) ce_inner decs in + let _, _, ce as scope = infer_block_decs env decs in + let t = infer_block_exps (adjoin env scope) decs in t, scope -and infer_block_exps env ce_inner decs : T.typ = +and infer_block_exps env decs : T.typ = match decs with | [] -> T.unit - | [dec] -> infer_dec env ce_inner dec + | [dec] -> infer_dec env dec | dec::decs' -> let errs1 = - if env.pre then [] else recover (check_dec env ce_inner T.unit) dec in - let t, errs2 = recover_with T.Non (infer_block_exps env ce_inner) decs' in + if env.pre then [] else recover (check_dec env T.unit) dec in + let t, errs2 = recover_with T.Non (infer_block_exps env) decs' in return_with t (errs1 @ errs2) -and infer_dec env ce_inner dec : T.typ = +and infer_dec env dec : T.typ = let t = match dec.it with | ExpD exp -> @@ -988,17 +946,15 @@ and infer_dec env ce_inner dec : T.typ = check_exp (adjoin_vals env'' ve) t2 exp end; t - | ClassD (id, tid, typbinds, sort, pat, fields) -> + | ClassD (id, tid, typbinds, sort, pat, id', fields) -> let t = T.Env.find id.it env.vals in if not env.pre then begin let _cs, _ts, te, ce = check_typ_binds env typbinds in let env' = adjoin_typs env te ce in - let c = T.Env.find tid.it env.typs in - let env' = (*env'*) add_typ env' tid.it c (Con.Env.find c ce_inner) in let _, ve = infer_pat_exhaustive env' pat in let env'' = {env' with labs = T.Env.empty; rets = None; async = false} in - ignore (infer_obj (adjoin_vals env'' ve) sort.it ("anon-self" @@ no_region) fields) + ignore (infer_obj (adjoin_vals env'' ve) sort.it id' fields) end; t | TypD _ -> @@ -1011,37 +967,34 @@ and infer_dec env ce_inner dec : T.typ = and check_block env t decs at : scope = - let scope, ce_inner = infer_block_decs env decs in -(*Printf.printf "[block] check expressions\n";*) - check_block_exps (adjoin env scope) ce_inner t decs at; -(*Printf.printf "[block] done\n";*) + let scope = infer_block_decs env decs in + check_block_exps (adjoin env scope) t decs at; scope -and check_block_exps env ce_inner t decs at = +and check_block_exps env t decs at = match decs with | [] -> if not (T.sub env.cons T.unit t) then error at "empty block cannot produce expected type\n %s" (T.string_of_typ_expand env.cons t) | [dec] -> - check_dec env ce_inner t dec + check_dec env t dec | dec::decs' -> - let errs1 = recover (check_dec env ce_inner T.unit) dec in - let errs2 = recover (check_block_exps env ce_inner t decs') at in + let errs1 = recover (check_dec env T.unit) dec in + let errs2 = recover (check_block_exps env t decs') at in return (errs1 @ errs2) -and check_dec env ce_inner t dec = - begin - match dec.it with - | ExpD exp -> - check_exp env t exp; - dec.note <- exp.note; +and check_dec env t dec = + match dec.it with + | ExpD exp -> + 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 | FuncD (id, [], pat, typ, exp) -> (* TBR: special-case unit? *) if T.eq env.cons t T.unit then - ignore (infer_dec env ce_inner dec) + ignore (infer_dec env dec) else (match T.nonopt env.cons t with | T.Func ([], t1, t2)-> @@ -1059,14 +1012,13 @@ and check_dec env ce_inner t dec = (T.string_of_typ t) ) *) - | _ -> - let t' = infer_dec env ce_inner dec in - (* TBR: special-case unit? *) - if not (T.eq env.cons t T.unit || T.sub env.cons t' t) then - error dec.at "expression of type\n %s\ncannot produce expected type\n %s" - (T.string_of_typ_expand env.cons t) - (T.string_of_typ_expand env.cons t'); - end; + | _ -> + let t' = infer_dec env dec in + (* TBR: special-case unit? *) + if not (T.eq env.cons t T.unit || T.sub env.cons t' t) then + error dec.at "expression of type\n %s\ncannot produce expected type\n %s" + (T.string_of_typ_expand env.cons t) + (T.string_of_typ_expand env.cons t') (* and print_ce = @@ -1080,24 +1032,17 @@ and print_ve = *) -and infer_block_decs env decs : scope * con_env = -(*Printf.printf "[block] gather types\n";*) +and infer_block_decs env decs : scope = let pre_ve, te, pre_ce = gather_block_typdecs decs in -(*Printf.printf "[block] pre-infer types\n";*) let env' = adjoin {env with pre = true} (pre_ve, te, pre_ce) in - let ce, _ = infer_block_typdecs env' decs in -(*Printf.printf "[block] infer types\n";*) + let ce = infer_block_typdecs env' decs in let env'' = adjoin env (pre_ve, te, ce) in - let ce', ce_inner = infer_block_typdecs env'' decs in + let _ce' = infer_block_typdecs env'' decs in (* TBR: assertion does not work for types with binders, due to stamping *) (* assert (ce = ce'); *) -(*print_ce ce;*) -(*Printf.printf "[block] gather values\n";*) let pre_ve' = gather_block_valdecs decs in -(*Printf.printf "[block] infer values\n";*) let ve = infer_block_valdecs (adjoin_vals env'' pre_ve') decs in -(*print_ve ve;*) - (ve, te, ce), ce_inner + (ve, te, ce) (* Pass 1: collect type identifiers and their arity *) @@ -1108,7 +1053,7 @@ and gather_block_typdecs decs : scope = and gather_dec_typdecs (ve, te, ce) dec : scope = match dec.it with | ExpD _ | LetD _ | VarD _ | FuncD _ -> ve, te, ce - | TypD (id, binds, _) | ClassD (_, id, binds, _, _, _) -> + | TypD (id, binds, _) | ClassD (_, id, binds, _, _, _, _) -> if T.Env.mem id.it te then error dec.at "duplicate definition for type %s in block" id.it; let cs = @@ -1118,7 +1063,7 @@ and gather_dec_typdecs (ve, te, ce) dec : scope = let pre_k = T.Abs (pre_tbs, T.Pre) in let ve' = match dec.it with - | ClassD (conid, _, _ , _, _, _) -> + | ClassD (conid, _, _ , _, _, _, _) -> let t2 = T.Con (c, List.map (fun c' -> T.Con (c', [])) cs) in T.Env.add conid.it (T.Func (T.Construct, T.Returns, pre_tbs, [T.Pre], [t2])) ve | _ -> ve @@ -1126,35 +1071,33 @@ and gather_dec_typdecs (ve, te, ce) dec : scope = (* Pass 2 and 3: infer type definitions *) -and infer_block_typdecs env decs : con_env * con_env = - let _env', ce, ce_inner = - List.fold_left (fun (env, ce, ce_inner) dec -> - let ce', ce_inner' = infer_dec_typdecs env dec in - adjoin_cons env ce', Con.Env.adjoin ce ce', - Con.Env.adjoin ce_inner ce_inner' - ) (env, Con.Env.empty, Con.Env.empty) decs - in ce, ce_inner - -and infer_dec_typdecs env dec : con_env * con_env = +and infer_block_typdecs env decs : con_env = + let _env', ce = + List.fold_left (fun (env, ce) dec -> + let ce' = infer_dec_typdecs env dec in + adjoin_cons env ce', Con.Env.adjoin ce ce' + ) (env, Con.Env.empty) decs + in ce + +and infer_dec_typdecs env dec : con_env = match dec.it with | ExpD _ | LetD _ | VarD _ | FuncD _ -> - Con.Env.empty, Con.Env.empty + Con.Env.empty | TypD (id, binds, typ) -> let c = T.Env.find id.it env.typs in let cs, ts, te, ce = check_typ_binds {env with pre = true} binds in let env' = adjoin_typs env te ce in let t = check_typ env' typ in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in - Con.Env.singleton c (T.Def (tbs, T.close cs t)), Con.Env.empty - | ClassD (conid, id, binds, sort, pat, fields) -> + Con.Env.singleton c (T.Def (tbs, T.close cs t)) + | ClassD (conid, id, binds, sort, pat, id', fields) -> let c = T.Env.find id.it env.typs in let cs, ts, te, ce = check_typ_binds {env with pre = true} binds in let env' = adjoin_typs {env with pre = true} te ce in let _, ve = infer_pat env' pat in - let t, t_inner = infer_obj (adjoin_vals env' ve) sort.it ("anon-self" @@ no_region) fields in + let t = infer_obj (adjoin_vals env' ve) sort.it id' fields in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in - Con.Env.singleton c (T.Abs (tbs, T.close cs t)), - Con.Env.singleton c (T.Abs (tbs, T.close cs t_inner)) + Con.Env.singleton c (T.Abs (tbs, T.close cs t)) (* Pass 4: collect value identifiers *) @@ -1167,7 +1110,7 @@ and gather_dec_valdecs ve dec : val_env = ve | LetD (pat, _) -> gather_pat ve pat - | VarD (id, _) | FuncD (_, id, _, _, _, _) | ClassD (id, _ , _, _, _, _) -> + | VarD (id, _) | FuncD (_, id, _, _, _, _) | ClassD (id, _ , _, _, _, _, _) -> if T.Env.mem id.it ve then error dec.at "duplicate definition for %s in block" id.it; T.Env.add id.it T.Pre ve @@ -1229,7 +1172,7 @@ and infer_dec_valdecs env dec : val_env = (T.Func (T.Call sort.it, c, tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2)) | TypD _ -> T.Env.empty - | ClassD (conid, id, typbinds, sort, pat, fields) -> + | ClassD (conid, id, typbinds, sort, pat, id', fields) -> let cs, ts, te, ce = check_typ_binds env typbinds in let env' = adjoin_typs env te ce in let c = T.Env.find id.it env.typs in diff --git a/test/run/account.as b/test/run/account.as index 5d4c2fed1d5..c52992967bd 100644 --- a/test/run/account.as +++ b/test/run/account.as @@ -1,4 +1,4 @@ -actor class Account(initialBalance : Int) { +actor class Account(initialBalance : Int) = this { private var balance : Int = initialBalance; getBalance() : async Int { @@ -10,15 +10,15 @@ actor class Account(initialBalance : Int) { return Account(amount); }; - join(account : Account) { // this implicitly asserts that account is Account + join(account : like Account) { + assert(account is Account); let amount = balance; - balance := +0; - account.credit(amount); + balance := 0; + account.credit(amount, Account); }; - private credit(amount : Int) { - // private implicitly asserts that caller is own class - // by implicitly passing the modref as an extra argument + credit(amount : Int, caller : Class) { + assert(this is caller); balance += amount; }; diff --git a/test/run/actor.as b/test/run/actor.as index 8c680a9f20b..ca7a23d3b97 100644 --- a/test/run/actor.as +++ b/test/run/actor.as @@ -68,7 +68,7 @@ let f = async { private get_a = await (async (func get_a() : async Text {a;})); private get_b = await (async (func get_b() : async Text {b;})); get_ab(): async (Text,Text) { - (await get_a(), await this.get_b()); + (await get_a(), await get_b()); }; }; let (a,b) = await(o.get_ab()); diff --git a/test/run/bank-example.as b/test/run/bank-example.as index 7dec3e5784e..12f1f7b50eb 100644 --- a/test/run/bank-example.as +++ b/test/run/bank-example.as @@ -12,7 +12,7 @@ actor class Issuer() { }; }; -actor class Account(initialBalance : Int) { +actor class Account(initialBalance : Int) = self { private var balance : Int = initialBalance; getBalance() : async Int { @@ -24,15 +24,15 @@ actor class Account(initialBalance : Int) { return Account(amount); }; - join(account : Account) { // this implicitly asserts that account is Account + join(account : like Account) { + assert(account is Account); let amount = balance; balance := 0; - account.credit(amount); + account.credit(amount, Account); }; - private credit(amount : Int) { - // private implicitly asserts that caller is own class - // by implicitly passing the modref as an extra argument + credit(amount : Int, caller : Class) { + assert(self is caller); balance += amount; }; diff --git a/test/run/bank-ordered.as b/test/run/bank-ordered.as index 9b722ba973d..3e62b2732e5 100644 --- a/test/run/bank-ordered.as +++ b/test/run/bank-ordered.as @@ -1,6 +1,6 @@ // Like bank.as but in dependency order -actor class Account(initialBalance : Int) { +actor class Account(initialBalance : Int) = this { private var balance : Int = initialBalance; getBalance() : async Int { @@ -12,15 +12,15 @@ actor class Account(initialBalance : Int) { return Account(amount); }; - join(account : Account) { // this implicitly asserts that account is Account + join(account : like Account) { + assert(account is Account); let amount = balance; balance := +0; // Hack! - account.credit(amount); + account.credit(amount, Account); }; - private credit(amount : Int) { - // private implicitly asserts that caller is own class - // by implicitly passing the modref as an extra argument + credit(amount : Int, caller : Class) { + assert(this is caller); balance += amount; }; diff --git a/test/run/bank.as b/test/run/bank.as index 77cc3fd8ca9..0747c8e6229 100644 --- a/test/run/bank.as +++ b/test/run/bank.as @@ -11,7 +11,7 @@ actor class Issuer() { }; }; -actor class Account(initialBalance : Int) { +actor class Account(initialBalance : Int) = self { private var balance : Int = initialBalance; getBalance() : async Int { @@ -23,15 +23,15 @@ actor class Account(initialBalance : Int) { return Account(amount); }; - join(account : Account) { // this implicitly asserts that account is Account + join(account : like Account) { + assert(account is Account); let amount = balance; balance := 0; - account.credit(amount); + account.credit(amount, Account); }; - private credit(amount : Int) { - // private implicitly asserts that caller is own class - // by implicitly passing the modref as an extra argument + credit(amount : Int, caller : Class) { + assert(self is caller); balance += amount; }; diff --git a/test/run/ok/account.wasm-run.ok b/test/run/ok/account.wasm-run.ok new file mode 100644 index 00000000000..d7648f54f23 --- /dev/null +++ b/test/run/ok/account.wasm-run.ok @@ -0,0 +1 @@ +_out/account.wasm:0x___: runtime trap: unreachable executed diff --git a/test/run/ok/account.wasm.stderr.ok b/test/run/ok/account.wasm.stderr.ok index 4ef479755e2..36cd23d940c 100644 --- a/test/run/ok/account.wasm.stderr.ok +++ b/test/run/ok/account.wasm.stderr.ok @@ -1 +1,2 @@ +Could not find this Could not find Account diff --git a/test/run/ok/bank-example.wasm-run.ok b/test/run/ok/bank-example.wasm-run.ok new file mode 100644 index 00000000000..b84483e8c59 --- /dev/null +++ b/test/run/ok/bank-example.wasm-run.ok @@ -0,0 +1 @@ +_out/bank-example.wasm:0x___: runtime trap: unreachable executed diff --git a/test/run/ok/bank-example.wasm.stderr.ok b/test/run/ok/bank-example.wasm.stderr.ok index 41346f1f179..a3a7bdead84 100644 --- a/test/run/ok/bank-example.wasm.stderr.ok +++ b/test/run/ok/bank-example.wasm.stderr.ok @@ -1,2 +1,3 @@ +Could not find self Could not find Account Could not find Account diff --git a/test/run/ok/bank-ordered.wasm-run.ok b/test/run/ok/bank-ordered.wasm-run.ok new file mode 100644 index 00000000000..d62cbfac5ec --- /dev/null +++ b/test/run/ok/bank-ordered.wasm-run.ok @@ -0,0 +1 @@ +_out/bank-ordered.wasm:0x___: runtime trap: unreachable executed diff --git a/test/run/ok/bank-ordered.wasm.stderr.ok b/test/run/ok/bank-ordered.wasm.stderr.ok index 41346f1f179..7e0dbb3aef3 100644 --- a/test/run/ok/bank-ordered.wasm.stderr.ok +++ b/test/run/ok/bank-ordered.wasm.stderr.ok @@ -1,2 +1,3 @@ Could not find Account +Could not find this Could not find Account diff --git a/test/run/ok/bank.wasm-run.ok b/test/run/ok/bank.wasm-run.ok new file mode 100644 index 00000000000..e491abe4726 --- /dev/null +++ b/test/run/ok/bank.wasm-run.ok @@ -0,0 +1 @@ +_out/bank.wasm:0x___: runtime trap: unreachable executed diff --git a/test/run/ok/bank.wasm.stderr.ok b/test/run/ok/bank.wasm.stderr.ok index 41346f1f179..a3a7bdead84 100644 --- a/test/run/ok/bank.wasm.stderr.ok +++ b/test/run/ok/bank.wasm.stderr.ok @@ -1,2 +1,3 @@ +Could not find self Could not find Account Could not find Account diff --git a/test/run/ok/this-dot-private.run-low.ok b/test/run/ok/this-dot-private.run-low.ok deleted file mode 100644 index 265c3b2ee24..00000000000 --- a/test/run/ok/this-dot-private.run-low.ok +++ /dev/null @@ -1 +0,0 @@ -fefb diff --git a/test/run/ok/this-dot-private.run.ok b/test/run/ok/this-dot-private.run.ok deleted file mode 100644 index 265c3b2ee24..00000000000 --- a/test/run/ok/this-dot-private.run.ok +++ /dev/null @@ -1 +0,0 @@ -fefb diff --git a/test/run/ok/this-dot-private.wasm-run.ok b/test/run/ok/this-dot-private.wasm-run.ok deleted file mode 100644 index a5166345e75..00000000000 --- a/test/run/ok/this-dot-private.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/this-dot-private.wasm:0x___: runtime trap: unreachable executed diff --git a/test/run/ok/this-dot-private.wasm.stderr.ok b/test/run/ok/this-dot-private.wasm.stderr.ok deleted file mode 100644 index 1958157334c..00000000000 --- a/test/run/ok/this-dot-private.wasm.stderr.ok +++ /dev/null @@ -1 +0,0 @@ -compile_exp: (NewObjE Actor get_ab get_ab@7 get_b get_b@6 get_a get_a@5 b b@4 a a@3) diff --git a/test/run/this-dot-private.as b/test/run/this-dot-private.as deleted file mode 100644 index 048a2248b3c..00000000000 --- a/test/run/this-dot-private.as +++ /dev/null @@ -1,17 +0,0 @@ -/* adapted from ../run/actor.as */ -let f = async { - let o = actor this { - private a = "fe"; - private b = "fb"; - private get_a = await (async (func get_a() : async Text {a;})); - private get_b = await (async (func get_b() : async Text {b;})); - get_ab(): async (Text,Text) { - let _ = (await this.get_a(), await this.get_b()); - (await get_a(), await get_b()) - }; - }; - let (a,b) = await(o.get_ab()); - print a; - print b; - print "\n"; -};